From 5d837780f5d149cb8d3b861c63a7dc4466a7cbf1 Mon Sep 17 00:00:00 2001
From: Dessalines <dessalines@users.noreply.github.com>
Date: Wed, 9 Nov 2022 05:05:00 -0500
Subject: [PATCH] Add diesel_async, get rid of blocking function (#2510)

* Moving settings to Database.

- Moves many settings into the database. Fixes #2285
- Adds a local_site and instance table. Fixes #2365 . Fixes #2368
- Separates SQL update an insert forms, to avoid runtime errors.
- Adds TypedBuilder to all the SQL forms, instead of default.

* Fix weird clippy issue.

* Removing extra lines.

* Some fixes from suggestions.

* Fixing apub tests.

* Using instance creation helper function.

* Move forms to their own line.

* Trying to fix local_site_data, still broken.

* Testing out async

* Testing out async 2

* Fixing federation tests.

* Trying to fix check features 1.

* Starting on adding diesel async. 1/4th done.

* Added async to views and schema.

* Adding some more async

* Compiling now.

* Added diesel async. Fixes #2465

* Running clippy --fix

* Trying to fix cargo test on drone.

* Trying new muslrust.

* Trying a custom dns

* Trying a custom dns 2

* Trying a custom dns 3

* Trying a custom dns 4

* Trying a custom dns 5

* Trying a custom dns 6

* Trying a custom dns 7

* Addressing PR comments.

* Adding check_apub to all verify functions.

* Reverting back drone.

* Fixing merge

* Fix docker images.

* Adding missing discussion_languages.

* Trying to fix federation tests.

* Fix site setup user creation.

* Fix clippy

* Fix clippy 2

* Test api faster

* Try to fix 1

* Try to fix 2

* What are these lines about

* Trying to fix 3

* Moving federation test back to top.

* Remove logging cat.
---
 .drone.yml                                    |  11 +-
 Cargo.lock                                    | 895 ++++++++++++------
 Cargo.toml                                    |   5 +-
 api_tests/package.json                        |   2 +-
 api_tests/prepare-drone-federation-test.sh    |  46 +-
 api_tests/yarn.lock                           |   8 +-
 crates/api/Cargo.toml                         |  20 +-
 crates/api/src/comment/like.rs                |  31 +-
 crates/api/src/comment/save.rs                |  17 +-
 crates/api/src/comment_report/create.rs       |  22 +-
 crates/api/src/comment_report/list.rs         |  26 +-
 crates/api/src/comment_report/resolve.rs      |  33 +-
 crates/api/src/community/add_mod.rs           |  34 +-
 crates/api/src/community/ban.rs               |  44 +-
 crates/api/src/community/block.rs             |  31 +-
 crates/api/src/community/follow.rs            |  35 +-
 crates/api/src/community/hide.rs              |  15 +-
 crates/api/src/community/transfer.rs          |  43 +-
 crates/api/src/lib.rs                         |  24 +-
 crates/api/src/local_user/add_admin.rs        |  20 +-
 crates/api/src/local_user/ban_person.rs       |  36 +-
 crates/api/src/local_user/block.rs            |  17 +-
 crates/api/src/local_user/change_password.rs  |   8 +-
 .../local_user/change_password_after_reset.rs |  17 +-
 crates/api/src/local_user/get_captcha.rs      |   7 +-
 crates/api/src/local_user/list_banned.rs      |   4 +-
 crates/api/src/local_user/login.rs            |  12 +-
 .../local_user/notifications/list_mentions.rs |  28 +-
 .../local_user/notifications/list_replies.rs  |  28 +-
 .../local_user/notifications/mark_all_read.rs |  26 +-
 .../notifications/mark_mention_read.rs        |  23 +-
 .../notifications/mark_reply_read.rs          |  24 +-
 .../local_user/notifications/unread_count.rs  |  18 +-
 crates/api/src/local_user/report_count.rs     |  21 +-
 crates/api/src/local_user/reset_password.rs   |  10 +-
 crates/api/src/local_user/save_settings.rs    |  22 +-
 crates/api/src/local_user/verify_email.rs     |  26 +-
 crates/api/src/post/like.rs                   |  18 +-
 crates/api/src/post/lock.rs                   |  19 +-
 crates/api/src/post/mark_read.rs              |   7 +-
 crates/api/src/post/save.rs                   |  17 +-
 crates/api/src/post/sticky.rs                 |  23 +-
 crates/api/src/post_report/create.rs          |  22 +-
 crates/api/src/post_report/list.rs            |  26 +-
 crates/api/src/post_report/resolve.rs         |  35 +-
 crates/api/src/private_message/mark_read.rs   |  21 +-
 .../api/src/private_message_report/create.rs  |  23 +-
 crates/api/src/private_message_report/list.rs |  20 +-
 .../api/src/private_message_report/resolve.rs |  31 +-
 crates/api/src/site/leave_admin.rs            |  28 +-
 crates/api/src/site/mod_log.rs                | 147 +--
 crates/api/src/site/purge/comment.rs          |  14 +-
 crates/api/src/site/purge/community.rs        |  17 +-
 crates/api/src/site/purge/person.rs           |  11 +-
 crates/api/src/site/purge/post.rs             |  11 +-
 .../site/registration_applications/approve.rs |  24 +-
 .../site/registration_applications/list.rs    |  24 +-
 .../registration_applications/unread_count.rs |  10 +-
 crates/api/src/site/resolve_object.rs         |  13 +-
 crates/api/src/site/search.rs                 | 236 +++--
 crates/api_common/Cargo.toml                  |   4 +-
 crates/api_common/src/site.rs                 |   5 +-
 crates/api_common/src/utils.rs                | 232 ++---
 crates/api_crud/Cargo.toml                    |   6 +-
 crates/api_crud/src/comment/create.rs         |  92 +-
 crates/api_crud/src/comment/delete.rs         |  28 +-
 crates/api_crud/src/comment/list.rs           |  45 +-
 crates/api_crud/src/comment/read.rs           |  12 +-
 crates/api_crud/src/comment/remove.rs         |  33 +-
 crates/api_crud/src/comment/update.rs         |  26 +-
 crates/api_crud/src/community/create.rs       |  28 +-
 crates/api_crud/src/community/delete.rs       |  26 +-
 crates/api_crud/src/community/list.rs         |  26 +-
 crates/api_crud/src/community/read.rs         |  35 +-
 crates/api_crud/src/community/remove.rs       |  25 +-
 crates/api_crud/src/community/update.rs       |  30 +-
 crates/api_crud/src/post/create.rs            |  81 +-
 crates/api_crud/src/post/delete.rs            |  28 +-
 crates/api_crud/src/post/list.rs              |  33 +-
 crates/api_crud/src/post/read.rs              |  37 +-
 crates/api_crud/src/post/remove.rs            |  28 +-
 crates/api_crud/src/post/update.rs            |  20 +-
 crates/api_crud/src/private_message/create.rs |  60 +-
 crates/api_crud/src/private_message/delete.rs |  25 +-
 crates/api_crud/src/private_message/read.rs   |  22 +-
 crates/api_crud/src/private_message/update.rs |  29 +-
 crates/api_crud/src/site/create.rs            |  22 +-
 crates/api_crud/src/site/read.rs              |  51 +-
 crates/api_crud/src/site/update.rs            |  80 +-
 crates/api_crud/src/user/create.rs            |  51 +-
 crates/api_crud/src/user/read.rs              |  96 +-
 crates/apub/Cargo.toml                        |  15 +-
 .../apub/src/activities/block/block_user.rs   |  52 +-
 crates/apub/src/activities/block/mod.rs       |   5 +-
 .../src/activities/block/undo_block_user.rs   |  35 +-
 .../apub/src/activities/community/add_mod.rs  |  21 +-
 crates/apub/src/activities/community/mod.rs   |   2 +-
 .../src/activities/community/remove_mod.rs    |  15 +-
 .../apub/src/activities/community/report.rs   |  29 +-
 .../apub/src/activities/community/update.rs   |   9 +-
 .../activities/create_or_update/comment.rs    |  22 +-
 .../src/activities/create_or_update/mod.rs    |   5 +-
 .../src/activities/create_or_update/post.rs   |  12 +-
 .../create_or_update/private_message.rs       |   6 +-
 crates/apub/src/activities/deletion/delete.rs |  67 +-
 .../src/activities/deletion/delete_user.rs    |   2 +-
 crates/apub/src/activities/deletion/mod.rs    |  72 +-
 .../src/activities/deletion/undo_delete.rs    |  60 +-
 .../apub/src/activities/following/accept.rs   |  28 +-
 .../apub/src/activities/following/follow.rs   |  21 +-
 .../src/activities/following/undo_follow.rs   |  12 +-
 crates/apub/src/activities/mod.rs             |  26 +-
 crates/apub/src/activities/voting/mod.rs      |  25 +-
 .../apub/src/activities/voting/undo_vote.rs   |  11 +-
 crates/apub/src/activities/voting/vote.rs     |  25 +-
 .../src/collections/community_moderators.rs   |  62 +-
 .../apub/src/collections/community_outbox.rs  |  13 +-
 .../apub/src/fetcher/deletable_apub_object.rs |  33 +-
 crates/apub/src/fetcher/mod.rs                |  21 +-
 crates/apub/src/fetcher/search.rs             |   2 +-
 crates/apub/src/fetcher/webfinger.rs          |   5 +-
 crates/apub/src/http/comment.rs               |   5 +-
 crates/apub/src/http/community.rs             |  35 +-
 crates/apub/src/http/mod.rs                   |   8 +-
 crates/apub/src/http/person.rs                |  14 +-
 crates/apub/src/http/post.rs                  |   5 +-
 crates/apub/src/http/site.rs                  |   6 +-
 crates/apub/src/lib.rs                        |  95 +-
 crates/apub/src/mentions.rs                   |  12 +-
 crates/apub/src/objects/comment.rs            |  72 +-
 crates/apub/src/objects/community.rs          |  57 +-
 crates/apub/src/objects/instance.rs           |  38 +-
 crates/apub/src/objects/mod.rs                |  23 +-
 crates/apub/src/objects/person.rs             |  44 +-
 crates/apub/src/objects/post.rs               |  55 +-
 crates/apub/src/objects/private_message.rs    |  51 +-
 .../protocol/collections/group_followers.rs   |   7 +-
 crates/apub/src/protocol/mod.rs               |   2 +-
 crates/apub/src/protocol/objects/group.rs     |   4 +-
 crates/apub/src/protocol/objects/mod.rs       |  39 +-
 crates/apub/src/protocol/objects/note.rs      |   5 +-
 crates/apub/src/protocol/objects/page.rs      |   4 +-
 crates/db_schema/Cargo.toml                   |  10 +-
 .../src/aggregates/comment_aggregates.rs      |  68 +-
 .../src/aggregates/community_aggregates.rs    |  99 +-
 .../src/aggregates/person_aggregates.rs       |  98 +-
 .../src/aggregates/person_post_aggregates.rs  |  20 +-
 .../src/aggregates/post_aggregates.rs         |  74 +-
 .../src/aggregates/site_aggregates.rs         |  60 +-
 crates/db_schema/src/aggregates/structs.rs    |   4 +-
 crates/db_schema/src/impls/activity.rs        | 103 +-
 crates/db_schema/src/impls/actor_language.rs  | 517 +++++-----
 crates/db_schema/src/impls/comment.rs         | 154 +--
 crates/db_schema/src/impls/comment_reply.rs   |  90 +-
 crates/db_schema/src/impls/comment_report.rs  |  37 +-
 crates/db_schema/src/impls/community.rs       | 201 ++--
 crates/db_schema/src/impls/community_block.rs |  14 +-
 .../db_schema/src/impls/email_verification.rs |  36 +-
 .../src/impls/federation_allowlist.rs         |  77 +-
 .../src/impls/federation_blocklist.rs         |  57 +-
 crates/db_schema/src/impls/instance.rs        |  51 +-
 crates/db_schema/src/impls/language.rs        |  55 +-
 crates/db_schema/src/impls/local_site.rs      |  27 +-
 .../src/impls/local_site_rate_limit.rs        |  28 +-
 crates/db_schema/src/impls/local_user.rs      |  53 +-
 crates/db_schema/src/impls/moderator.rs       | 370 +++++---
 .../src/impls/password_reset_request.rs       |  58 +-
 crates/db_schema/src/impls/person.rs          |  82 +-
 crates/db_schema/src/impls/person_block.rs    |  23 +-
 crates/db_schema/src/impls/person_mention.rs  |  88 +-
 crates/db_schema/src/impls/post.rs            | 166 ++--
 crates/db_schema/src/impls/post_report.rs     |  40 +-
 crates/db_schema/src/impls/private_message.rs |  84 +-
 .../src/impls/private_message_report.rs       |  42 +-
 .../src/impls/registration_application.rs     |  46 +-
 crates/db_schema/src/impls/secret.rs          |  21 +-
 crates/db_schema/src/impls/site.rs            |  47 +-
 crates/db_schema/src/lib.rs                   |   3 +
 crates/db_schema/src/traits.rs                |  90 +-
 crates/db_schema/src/utils.rs                 |  82 +-
 crates/db_views/Cargo.toml                    |  10 +-
 crates/db_views/src/comment_report_view.rs    | 122 ++-
 crates/db_views/src/comment_view.rs           | 194 ++--
 .../local_user_discussion_language_view.rs    |  13 +-
 crates/db_views/src/local_user_view.rs        |  51 +-
 crates/db_views/src/post_report_view.rs       | 113 ++-
 crates/db_views/src/post_view.rs              | 203 ++--
 .../src/private_message_report_view.rs        |  56 +-
 crates/db_views/src/private_message_view.rs   |  36 +-
 .../src/registration_application_view.rs      | 117 ++-
 crates/db_views/src/site_view.rs              |  10 +-
 crates/db_views_actor/Cargo.toml              |   7 +-
 .../db_views_actor/src/comment_reply_view.rs  |  34 +-
 .../src/community_block_view.rs               |  10 +-
 .../src/community_follower_view.rs            |  19 +-
 .../src/community_moderator_view.rs           |  25 +-
 .../src/community_person_ban_view.rs          |  12 +-
 crates/db_views_actor/src/community_view.rs   |  47 +-
 .../db_views_actor/src/person_block_view.rs   |  10 +-
 .../db_views_actor/src/person_mention_view.rs |  36 +-
 crates/db_views_actor/src/person_view.rs      |  38 +-
 crates/db_views_moderator/Cargo.toml          |   7 +-
 .../src/admin_purge_comment_view.rs           |  19 +-
 .../src/admin_purge_community_view.rs         |  19 +-
 .../src/admin_purge_person_view.rs            |  20 +-
 .../src/admin_purge_post_view.rs              |  20 +-
 .../src/mod_add_community_view.rs             |  19 +-
 crates/db_views_moderator/src/mod_add_view.rs |  19 +-
 .../src/mod_ban_from_community_view.rs        |  20 +-
 crates/db_views_moderator/src/mod_ban_view.rs |  19 +-
 .../src/mod_hide_community_view.rs            |  20 +-
 .../src/mod_lock_post_view.rs                 |  20 +-
 .../src/mod_remove_comment_view.rs            |  19 +-
 .../src/mod_remove_community_view.rs          |  19 +-
 .../src/mod_remove_post_view.rs               |  20 +-
 .../src/mod_sticky_post_view.rs               |  19 +-
 .../src/mod_transfer_community_view.rs        |  20 +-
 crates/routes/Cargo.toml                      |  10 +-
 crates/routes/src/feeds.rs                    | 116 +--
 crates/routes/src/images.rs                   |   7 +-
 crates/routes/src/nodeinfo.rs                 |   5 +-
 crates/routes/src/webfinger.rs                |  21 +-
 crates/utils/Cargo.toml                       |  18 +-
 crates/websocket/Cargo.toml                   |  16 +-
 crates/websocket/src/chat_server.rs           |   9 +-
 crates/websocket/src/send.rs                  |  71 +-
 docker/dev/Dockerfile                         |   2 +-
 docker/dev/docker-compose.yml                 |   8 +-
 docker/dev/lemmy.hjson                        |   4 -
 docker/federation/lemmy_alpha.hjson           |   5 +-
 docker/federation/lemmy_beta.hjson            |   4 +-
 docker/federation/lemmy_delta.hjson           |   4 +-
 docker/federation/lemmy_epsilon.hjson         |   4 +-
 docker/federation/lemmy_gamma.hjson           |   4 +-
 docker/prod/Dockerfile                        |   2 +-
 docker/prod/Dockerfile.arm                    |   2 +-
 src/code_migrations.rs                        | 154 +--
 src/main.rs                                   |  47 +-
 src/scheduled_tasks.rs                        |  26 +-
 239 files changed, 5362 insertions(+), 4910 deletions(-)

diff --git a/.drone.yml b/.drone.yml
index 9f7e2252..fa96258b 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -10,8 +10,7 @@ steps:
 
   # use minimum supported rust version for most steps
   - name: prepare repo
-    image: clux/muslrust:1.59.0
-    user: root
+    image: clux/muslrust:1.64.0
     commands:
       - git fetch --tags
       - git submodule init
@@ -34,7 +33,7 @@ steps:
       - cargo clippy --workspace --all-features -- -D clippy::unwrap_used
 
   - name: cargo test
-    image: clux/muslrust:1.59.0
+    image: clux/muslrust:1.64.0
     environment:
       LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
       LEMMY_CONFIG_LOCATION: ../../config/config.hjson
@@ -46,20 +45,20 @@ steps:
       - cargo test --workspace --no-fail-fast --all-features
 
   - name: check defaults.hjson updated
-    image: clux/muslrust:1.59.0
+    image: clux/muslrust:1.64.0
     commands:
       - ./scripts/update_config_defaults.sh config/defaults_current.hjson
       - diff config/defaults.hjson config/defaults_current.hjson
 
   - name: check with different features
-    image: clux/muslrust:1.59.0
+    image: clux/muslrust:1.64.0
     commands:
       - cargo install cargo-workspaces
       - cargo workspaces exec cargo check --no-default-features
       - cargo workspaces exec cargo check --all-features
 
   - name: cargo build
-    image: clux/muslrust:1.59.0
+    image: clux/muslrust:1.64.0
     commands:
       - cargo build
       - mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server
diff --git a/Cargo.lock b/Cargo.lock
index 8d50197b..1d6f2940 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -12,7 +12,7 @@ dependencies = [
  "actix-web",
  "anyhow",
  "async-trait",
- "background-jobs 0.13.0",
+ "background-jobs",
  "base64",
  "chrono",
  "derive_builder 0.11.2",
@@ -39,9 +39,9 @@ version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "07520b54fc0f22ad30b90399b2a2689c6e5c113df0642ca3fa2f7ee823e54126"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -137,7 +137,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
 dependencies = [
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -213,9 +213,9 @@ dependencies = [
 
 [[package]]
 name = "actix-utils"
-version = "3.0.0"
+version = "3.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e491cbaac2e7fc788dfff99ff48ef317e23b3cf63dbaf7aaab6418f40f92aa94"
+checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
 dependencies = [
  "local-waker",
  "pin-project-lite",
@@ -259,7 +259,7 @@ dependencies = [
  "serde_urlencoded",
  "smallvec",
  "socket2",
- "time 0.3.14",
+ "time 0.3.15",
  "url",
 ]
 
@@ -287,9 +287,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13"
 dependencies = [
  "actix-router",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -298,9 +298,9 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -315,7 +315,7 @@ version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
  "once_cell",
  "version_check",
 ]
@@ -338,20 +338,11 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "ansi_term"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "anyhow"
-version = "1.0.65"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602"
+checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "arrayvec"
@@ -394,20 +385,20 @@ version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
 name = "async-trait"
-version = "0.1.57"
+version = "0.1.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
+checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -431,9 +422,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "axum"
-version = "0.5.16"
+version = "0.5.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9e3356844c4d6a6d6467b8da2cffb4a2820be256f50a3a386c9d152bab31043"
+checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -460,9 +451,9 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9f0c0a60006f2a293d82d571f635042a72edf927539b7685bd62d361963839b"
+checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc"
 dependencies = [
  "async-trait",
  "bytes",
@@ -474,45 +465,14 @@ dependencies = [
  "tower-service",
 ]
 
-[[package]]
-name = "background-jobs"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c301b3ccb60fa2aadb4da111e27b257ddc4f0509848c43c85764dc14f7a49a3"
-dependencies = [
- "background-jobs-actix 0.12.0",
- "background-jobs-core 0.12.0",
-]
-
 [[package]]
 name = "background-jobs"
 version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "793a813f9145c5f3a27b8dcd834c0927de68bbd60d53a369e5894f3cc5759020"
 dependencies = [
- "background-jobs-actix 0.13.0",
- "background-jobs-core 0.13.0",
-]
-
-[[package]]
-name = "background-jobs-actix"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "65a0dcbc94e0644fcfbaddc19705fae2d6947426682aeab7582d772f4d80b8df"
-dependencies = [
- "actix-rt",
- "anyhow",
- "async-mutex",
- "async-trait",
- "background-jobs-core 0.12.0",
- "num_cpus",
- "serde",
- "serde_json",
- "thiserror",
- "tokio",
- "tracing",
- "tracing-futures",
- "uuid 0.8.2",
+ "background-jobs-actix",
+ "background-jobs-core",
 ]
 
 [[package]]
@@ -525,7 +485,7 @@ dependencies = [
  "anyhow",
  "async-mutex",
  "async-trait",
- "background-jobs-core 0.13.0",
+ "background-jobs-core",
  "num_cpus",
  "serde",
  "serde_json",
@@ -533,26 +493,7 @@ dependencies = [
  "tokio",
  "tracing",
  "tracing-futures",
- "uuid 1.1.2",
-]
-
-[[package]]
-name = "background-jobs-core"
-version = "0.12.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82fe510c99cea8b98c438e81f43c666e9b4cd3630a42a1684ed1d01db4271cfb"
-dependencies = [
- "actix-rt",
- "anyhow",
- "async-mutex",
- "async-trait",
- "serde",
- "serde_json",
- "thiserror",
- "time 0.3.14",
- "tracing",
- "tracing-futures",
- "uuid 0.8.2",
+ "uuid",
 ]
 
 [[package]]
@@ -568,17 +509,30 @@ dependencies = [
  "serde",
  "serde_json",
  "thiserror",
- "time 0.3.14",
+ "time 0.3.15",
  "tracing",
  "tracing-futures",
- "uuid 1.1.2",
+ "uuid",
 ]
 
 [[package]]
 name = "base64"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
+checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+
+[[package]]
+name = "bb8"
+version = "0.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1627eccf3aa91405435ba240be23513eeca466b5dc33866422672264de061582"
+dependencies = [
+ "async-trait",
+ "futures-channel",
+ "futures-util",
+ "parking_lot",
+ "tokio",
+]
 
 [[package]]
 name = "bcrypt"
@@ -588,7 +542,7 @@ checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641"
 dependencies = [
  "base64",
  "blowfish",
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
  "zeroize",
 ]
 
@@ -646,9 +600,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.11.0"
+version = "3.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
 
 [[package]]
 name = "bytemuck"
@@ -744,6 +698,16 @@ dependencies = [
  "chrono",
 ]
 
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
 [[package]]
 name = "color_quant"
 version = "1.1.0"
@@ -786,7 +750,7 @@ checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86"
 dependencies = [
  "prost 0.11.0",
  "prost-types 0.11.1",
- "tonic 0.8.1",
+ "tonic 0.8.2",
  "tracing-core",
 ]
 
@@ -808,7 +772,7 @@ dependencies = [
  "thread_local",
  "tokio",
  "tokio-stream",
- "tonic 0.8.1",
+ "tonic 0.8.2",
  "tracing",
  "tracing-core",
  "tracing-subscriber",
@@ -822,12 +786,12 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 
 [[package]]
 name = "cookie"
-version = "0.16.0"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
+checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917"
 dependencies = [
  "percent-encoding",
- "time 0.3.14",
+ "time 0.3.15",
  "version_check",
 ]
 
@@ -877,12 +841,11 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.11"
+version = "0.8.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac"
 dependencies = [
  "cfg-if",
- "once_cell",
 ]
 
 [[package]]
@@ -895,6 +858,50 @@ dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "cxx"
+version = "1.0.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2 1.0.47",
+ "quote 1.0.21",
+ "scratch",
+ "syn 1.0.103",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
+dependencies = [
+ "proc-macro2 1.0.47",
+ "quote 1.0.21",
+ "syn 1.0.103",
+]
+
 [[package]]
 name = "darling"
 version = "0.12.4"
@@ -933,10 +940,10 @@ checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "strsim",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -947,10 +954,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "strsim",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -961,10 +968,10 @@ checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
 dependencies = [
  "fnv",
  "ident_case",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "strsim",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -975,7 +982,7 @@ checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
 dependencies = [
  "darling_core 0.12.4",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -986,7 +993,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
 dependencies = [
  "darling_core 0.13.4",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -997,7 +1004,7 @@ checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
 dependencies = [
  "darling_core 0.14.1",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1038,9 +1045,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
 dependencies = [
  "darling 0.12.4",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1050,9 +1057,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
 dependencies = [
  "darling 0.14.1",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1062,7 +1069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
 dependencies = [
  "derive_builder_core 0.10.2",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1072,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
 dependencies = [
  "derive_builder_core 0.11.2",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1082,10 +1089,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
 dependencies = [
  "convert_case",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "rustc_version",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1099,9 +1106,9 @@ dependencies = [
 
 [[package]]
 name = "diesel"
-version = "2.0.0"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01e2adfd0a7a81070ed7beec0c62636458926326c16fedb77796d41e447b282d"
+checksum = "68c186a7418a2aac330bb76cde82f16c36b03a66fb91db32d20214311f9f6545"
 dependencies = [
  "bitflags",
  "byteorder",
@@ -1109,10 +1116,23 @@ dependencies = [
  "diesel_derives",
  "itoa",
  "pq-sys",
- "r2d2",
  "serde_json",
 ]
 
+[[package]]
+name = "diesel-async"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "588383fa6d12fb17edf0fda88942222bbad070d185b5dcc3ac4d8354ce84b583"
+dependencies = [
+ "async-trait",
+ "bb8",
+ "diesel",
+ "futures",
+ "tokio",
+ "tokio-postgres",
+]
+
 [[package]]
 name = "diesel-derive-newtype"
 version = "2.0.0-rc.0"
@@ -1126,14 +1146,14 @@ dependencies = [
 
 [[package]]
 name = "diesel_derives"
-version = "2.0.0"
+version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22a7ab9d7967e6a1a247ea38aedf88ab808b4ac0c159576bc71866ab8f9f9250"
+checksum = "143b758c91dbc3fe1fdcb0dba5bd13276c6a66422f2ef5795b58488248a310aa"
 dependencies = [
  "proc-macro-error",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1165,6 +1185,7 @@ checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c"
 dependencies = [
  "block-buffer",
  "crypto-common",
+ "subtle",
 ]
 
 [[package]]
@@ -1215,9 +1236,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6430bef5fcbfa22f3c431f05a14254d45f41ab634cabe09fad82e98d4f9fdc8b"
 dependencies = [
  "darling 0.13.4",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1333,6 +1354,12 @@ version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
 [[package]]
 name = "fallible_collections"
 version = "0.4.5"
@@ -1415,9 +1442,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
+checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1430,9 +1457,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
+checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1440,15 +1467,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
+checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
+checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1457,38 +1484,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
+checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
+checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
+checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
 
 [[package]]
 name = "futures-task"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
+checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
 
 [[package]]
 name = "futures-util"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
+checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1525,9 +1552,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1599,6 +1626,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hmac"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+dependencies = [
+ "digest",
+]
+
 [[package]]
 name = "hostname"
 version = "0.3.1"
@@ -1632,9 +1668,9 @@ dependencies = [
 
 [[package]]
 name = "html2text"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "617dbbb43af195e64f03eef3b9e412d8374764d88a554332624d83d782da7267"
+checksum = "db2a75f4fdb748c0980b4d04f8edafc749bf4b5bfa738bf6c1565c7e6118d6ca"
 dependencies = [
  "html5ever 0.26.0",
  "markup5ever 0.11.0",
@@ -1652,9 +1688,9 @@ dependencies = [
  "log",
  "mac",
  "markup5ever 0.10.1",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1666,9 +1702,9 @@ dependencies = [
  "log",
  "mac",
  "markup5ever 0.11.0",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -1814,17 +1850,28 @@ dependencies = [
 
 [[package]]
 name = "iana-time-zone"
-version = "0.1.50"
+version = "0.1.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0"
+checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed"
 dependencies = [
  "android_system_properties",
  "core-foundation-sys",
+ "iana-time-zone-haiku",
  "js-sys",
  "wasm-bindgen",
  "winapi",
 ]
 
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
 [[package]]
 name = "ident_case"
 version = "1.0.1"
@@ -1854,9 +1901,9 @@ dependencies = [
 
 [[package]]
 name = "image"
-version = "0.24.3"
+version = "0.24.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e30ca2ecf7666107ff827a8e481de6a132a9b687ed3bb20bb1c144a36c00964"
+checksum = "bd8e4fb07cf672b1642304e731ef8a6a4c7891d67bb4fd4f5ce58cd6ed86803c"
 dependencies = [
  "bytemuck",
  "byteorder",
@@ -1911,9 +1958,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
 
 [[package]]
 name = "jni"
@@ -1993,8 +2040,10 @@ dependencies = [
  "lemmy_websocket",
  "serde",
  "serde_json",
+ "serial_test",
+ "tokio",
  "tracing",
- "uuid 1.1.2",
+ "uuid",
 ]
 
 [[package]]
@@ -2079,9 +2128,10 @@ dependencies = [
  "sha2",
  "strum_macros",
  "task-local-extensions",
+ "tokio",
  "tracing",
  "url",
- "uuid 1.1.2",
+ "uuid",
 ]
 
 [[package]]
@@ -2089,9 +2139,12 @@ name = "lemmy_db_schema"
 version = "0.16.5"
 dependencies = [
  "activitypub_federation",
+ "async-trait",
+ "bb8",
  "bcrypt",
  "chrono",
  "diesel",
+ "diesel-async",
  "diesel-derive-newtype",
  "diesel_ltree",
  "diesel_migrations",
@@ -2104,6 +2157,7 @@ dependencies = [
  "sha2",
  "strum",
  "strum_macros",
+ "tokio",
  "typed-builder",
  "url",
 ]
@@ -2113,10 +2167,12 @@ name = "lemmy_db_views"
 version = "0.16.5"
 dependencies = [
  "diesel",
+ "diesel-async",
  "diesel_ltree",
  "lemmy_db_schema",
  "serde",
  "serial_test",
+ "tokio",
  "tracing",
  "typed-builder",
  "url",
@@ -2127,6 +2183,7 @@ name = "lemmy_db_views_actor"
 version = "0.16.5"
 dependencies = [
  "diesel",
+ "diesel-async",
  "lemmy_db_schema",
  "serde",
  "typed-builder",
@@ -2137,6 +2194,7 @@ name = "lemmy_db_views_moderator"
 version = "0.16.5"
 dependencies = [
  "diesel",
+ "diesel-async",
  "lemmy_db_schema",
  "serde",
 ]
@@ -2178,6 +2236,7 @@ dependencies = [
  "clokwerk",
  "console-subscriber",
  "diesel",
+ "diesel-async",
  "diesel_migrations",
  "doku",
  "lemmy_api",
@@ -2240,7 +2299,7 @@ dependencies = [
  "tracing-error",
  "typed-builder",
  "url",
- "uuid 1.1.2",
+ "uuid",
 ]
 
 [[package]]
@@ -2251,7 +2310,7 @@ dependencies = [
  "actix-web",
  "actix-web-actors",
  "anyhow",
- "background-jobs 0.12.0",
+ "background-jobs",
  "chrono",
  "diesel",
  "lemmy_api_common",
@@ -2259,7 +2318,7 @@ dependencies = [
  "lemmy_db_views",
  "lemmy_db_views_actor",
  "lemmy_utils",
- "opentelemetry 0.17.0",
+ "opentelemetry 0.18.0",
  "rand 0.8.5",
  "reqwest-middleware",
  "serde",
@@ -2268,7 +2327,7 @@ dependencies = [
  "strum_macros",
  "tokio",
  "tracing",
- "tracing-opentelemetry 0.17.4",
+ "tracing-opentelemetry 0.18.0",
 ]
 
 [[package]]
@@ -2308,9 +2367,18 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.133"
+version = "0.2.135"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+
+[[package]]
+name = "link-cplusplus"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369"
+dependencies = [
+ "cc",
+]
 
 [[package]]
 name = "local-channel"
@@ -2342,9 +2410,9 @@ dependencies = [
 
 [[package]]
 name = "lodepng"
-version = "3.7.0"
+version = "3.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff45534ec797452c044fcd47861059eddb501e30a8fd9fdadea7957cdff3ebc7"
+checksum = "f0ad39f75bbaa4b10bb6f2316543632a8046a5bcf9c785488d79720b21f044f8"
 dependencies = [
  "crc32fast",
  "fallible_collections",
@@ -2435,6 +2503,15 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
 
+[[package]]
+name = "md-5"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca"
+dependencies = [
+ "digest",
+]
+
 [[package]]
 name = "memchr"
 version = "2.5.0"
@@ -2458,7 +2535,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a8ff27a350511de30cdabb77147501c36ef02e0451d957abea2f30caffb2b58"
 dependencies = [
  "migrations_internals",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
 ]
 
@@ -2502,7 +2579,7 @@ dependencies = [
  "libc",
  "log",
  "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys",
+ "windows-sys 0.36.1",
 ]
 
 [[package]]
@@ -2564,6 +2641,16 @@ dependencies = [
  "minimal-lexical",
 ]
 
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
 [[package]]
 name = "num-bigint"
 version = "0.4.3"
@@ -2651,9 +2738,9 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -2713,6 +2800,16 @@ dependencies = [
  "tokio-stream",
 ]
 
+[[package]]
+name = "opentelemetry"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e"
+dependencies = [
+ "opentelemetry_api",
+ "opentelemetry_sdk",
+]
+
 [[package]]
 name = "opentelemetry-otlp"
 version = "0.10.0"
@@ -2731,6 +2828,48 @@ dependencies = [
  "tonic-build",
 ]
 
+[[package]]
+name = "opentelemetry_api"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c24f96e21e7acc813c7a8394ee94978929db2bcc46cf6b5014fc612bf7760c22"
+dependencies = [
+ "fnv",
+ "futures-channel",
+ "futures-util",
+ "indexmap",
+ "js-sys",
+ "once_cell",
+ "pin-project-lite",
+ "thiserror",
+]
+
+[[package]]
+name = "opentelemetry_sdk"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ca41c4933371b61c2a2f214bf16931499af4ec90543604ec828f7a625c09113"
+dependencies = [
+ "async-trait",
+ "crossbeam-channel",
+ "dashmap",
+ "fnv",
+ "futures-channel",
+ "futures-executor",
+ "futures-util",
+ "once_cell",
+ "opentelemetry_api",
+ "percent-encoding",
+ "rand 0.8.5",
+ "thiserror",
+]
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
 [[package]]
 name = "parking_lot"
 version = "0.12.1"
@@ -2743,15 +2882,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.3"
+version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -2777,9 +2916,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb779fcf4bb850fbbb0edc96ff6cf34fd90c4b1a112ce042653280d9a7364048"
+checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2787,9 +2926,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "502b62a6d0245378b04ffe0a7fb4f4419a4815fce813bd8a0ec89a56e07d67b1"
+checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2797,22 +2936,22 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "451e629bf49b750254da26132f1a5a9d11fd8a95a3df51d15c4abd1ba154cb6c"
+checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db"
 dependencies = [
  "pest",
  "pest_meta",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcec162c71c45e269dfc3fc2916eaeb97feab22993a21bcce4721d08cd7801a6"
+checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d"
 dependencies = [
  "once_cell",
  "pest",
@@ -2847,6 +2986,15 @@ dependencies = [
  "phf_shared 0.10.0",
 ]
 
+[[package]]
+name = "phf"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "928c6535de93548188ef63bb7c4036bd415cd8f36ad25af44b9789b2ee72a48c"
+dependencies = [
+ "phf_shared 0.11.1",
+]
+
 [[package]]
 name = "phf_codegen"
 version = "0.8.0"
@@ -2905,6 +3053,15 @@ dependencies = [
  "siphasher",
 ]
 
+[[package]]
+name = "phf_shared"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1fb5f6f826b772a8d4c0394209441e7d37cbbb967ae9c7e0e8134365c9ee676"
+dependencies = [
+ "siphasher",
+]
+
 [[package]]
 name = "pin-project"
 version = "1.0.12"
@@ -2920,9 +3077,9 @@ version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -2955,6 +3112,35 @@ dependencies = [
  "miniz_oxide",
 ]
 
+[[package]]
+name = "postgres-protocol"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "878c6cbf956e03af9aa8204b407b9cbf47c072164800aa918c516cd4b056c50c"
+dependencies = [
+ "base64",
+ "byteorder",
+ "bytes",
+ "fallible-iterator",
+ "hmac",
+ "md-5",
+ "memchr",
+ "rand 0.8.5",
+ "sha2",
+ "stringprep",
+]
+
+[[package]]
+name = "postgres-types"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73d946ec7d256b04dfadc4e6a3292324e6f417124750fc5c0950f981b703a0f1"
+dependencies = [
+ "bytes",
+ "fallible-iterator",
+ "postgres-protocol",
+]
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.16"
@@ -2983,9 +3169,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
 dependencies = [
  "proc-macro-error-attr",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
  "version_check",
 ]
 
@@ -2995,7 +3181,7 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "version_check",
 ]
@@ -3011,9 +3197,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.43"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
+checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
 dependencies = [
  "unicode-ident",
 ]
@@ -3066,9 +3252,9 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
 dependencies = [
  "anyhow",
  "itertools",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3079,9 +3265,9 @@ checksum = "7345d5f0e08c0536d7ac7229952590239e77abf0a0100a1b1d890add6ea96364"
 dependencies = [
  "anyhow",
  "itertools",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3129,7 +3315,7 @@ version = "1.0.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
 ]
 
 [[package]]
@@ -3138,17 +3324,6 @@ version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fee2dce59f7a43418e3382c766554c614e06a552d53a8f07ef499ea4b332c0f"
 
-[[package]]
-name = "r2d2"
-version = "0.8.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93"
-dependencies = [
- "log",
- "parking_lot",
- "scheduled-thread-pool",
-]
-
 [[package]]
 name = "radium"
 version = "0.5.3"
@@ -3215,7 +3390,7 @@ version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
 ]
 
 [[package]]
@@ -3251,7 +3426,7 @@ version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
  "redox_syscall",
  "thiserror",
 ]
@@ -3425,7 +3600,7 @@ checksum = "6f697b8b3f19bee20f30dc87213d05ce091c43bc733ab1bfc98b0e5cdd9943f3"
 dependencies = [
  "convert_case",
  "lazy_static",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "regex",
  "tinyjson",
@@ -3460,9 +3635,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.20.6"
+version = "0.20.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
+checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
 dependencies = [
  "log",
  "ring",
@@ -3498,16 +3673,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
 dependencies = [
  "lazy_static",
- "windows-sys",
-]
-
-[[package]]
-name = "scheduled-thread-pool"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "977a7519bff143a44f842fd07e80ad1329295bd71686457f18e496736f4bf9bf"
-dependencies = [
- "parking_lot",
+ "windows-sys 0.36.1",
 ]
 
 [[package]]
@@ -3516,6 +3682,12 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "scratch"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
+
 [[package]]
 name = "sct"
 version = "0.7.0"
@@ -3568,29 +3740,29 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
 
 [[package]]
 name = "serde"
-version = "1.0.145"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.145"
+version = "1.0.147"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.85"
+version = "1.0.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
 dependencies = [
  "indexmap",
  "itoa",
@@ -3627,9 +3799,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
 dependencies = [
  "darling 0.13.4",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3653,9 +3825,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4b6f5d1c3087fb119617cff2966fe3808a80e5eb59a8c1601d5994d66f4346a5"
 dependencies = [
  "proc-macro-error",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3713,7 +3885,7 @@ dependencies = [
  "num-bigint",
  "num-traits",
  "thiserror",
- "time 0.3.14",
+ "time 0.3.15",
 ]
 
 [[package]]
@@ -3733,9 +3905,9 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "smart-default"
@@ -3743,9 +3915,9 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3792,10 +3964,20 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
 dependencies = [
  "phf_generator 0.10.0",
  "phf_shared 0.10.0",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
 ]
 
+[[package]]
+name = "stringprep"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
 [[package]]
 name = "strsim"
 version = "0.10.0"
@@ -3815,12 +3997,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
 dependencies = [
  "heck 0.4.0",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "rustversion",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
+[[package]]
+name = "subtle"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+
 [[package]]
 name = "syn"
 version = "0.14.9"
@@ -3834,11 +4022,11 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.100"
+version = "1.0.103"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e"
+checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
  "unicode-ident",
 ]
@@ -3889,6 +4077,15 @@ dependencies = [
  "utf-8",
 ]
 
+[[package]]
+name = "termcolor"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "thiserror"
 version = "1.0.37"
@@ -3904,9 +4101,9 @@ version = "1.0.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -3931,9 +4128,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.14"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b"
+checksum = "d634a985c4d4238ec39cacaed2e7ae552fbd3c476b552c1deac3021b7d7eaf0c"
 dependencies = [
  "itoa",
  "libc",
@@ -3971,9 +4168,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
 name = "tokio"
-version = "1.21.1"
+version = "1.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0020c875007ad96677dcc890298f4b942882c5d4eb7cc8f439fc3bf813dc9c95"
+checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3981,7 +4178,6 @@ dependencies = [
  "memchr",
  "mio",
  "num_cpus",
- "once_cell",
  "parking_lot",
  "pin-project-lite",
  "signal-hook-registry",
@@ -4007,9 +4203,9 @@ version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -4022,6 +4218,30 @@ dependencies = [
  "tokio",
 ]
 
+[[package]]
+name = "tokio-postgres"
+version = "0.7.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "29a12c1b3e0704ae7dfc25562629798b29c72e6b1d0a681b6f29ab4ae5e7f7bf"
+dependencies = [
+ "async-trait",
+ "byteorder",
+ "bytes",
+ "fallible-iterator",
+ "futures-channel",
+ "futures-util",
+ "log",
+ "parking_lot",
+ "percent-encoding",
+ "phf 0.11.1",
+ "pin-project-lite",
+ "postgres-protocol",
+ "postgres-types",
+ "socket2",
+ "tokio",
+ "tokio-util 0.7.4",
+]
+
 [[package]]
 name = "tokio-rustls"
 version = "0.23.4"
@@ -4035,9 +4255,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.10"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6edf2d6bc038a43d31353570e27270603f4648d18f5ed10c0e179abe43255af"
+checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -4114,9 +4334,9 @@ dependencies = [
 
 [[package]]
 name = "tonic"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11cd56bdb54ef93935a6a79dbd1d91f1ebd4c64150fd61654031fd6b8b775c91"
+checksum = "55b9af819e54b8f33d453655bef9b9acc171568fb49523078d0cc4e7484200ec"
 dependencies = [
  "async-stream",
  "async-trait",
@@ -4150,10 +4370,10 @@ version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "prost-build",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -4197,9 +4417,9 @@ dependencies = [
 
 [[package]]
 name = "tower-layer"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "343bc9466d3fe6b0f960ef45960509f84480bf4fd96f92901afe7ff3df9d3a62"
+checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
 
 [[package]]
 name = "tower-service"
@@ -4209,9 +4429,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
 
 [[package]]
 name = "tracing"
-version = "0.1.36"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if",
  "log",
@@ -4229,25 +4449,25 @@ dependencies = [
  "actix-web",
  "pin-project",
  "tracing",
- "uuid 1.1.2",
+ "uuid",
 ]
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2"
+checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
 name = "tracing-core"
-version = "0.1.29"
+version = "0.1.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7"
+checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
 dependencies = [
  "once_cell",
  "valuable",
@@ -4311,14 +4531,28 @@ dependencies = [
  "tracing-subscriber",
 ]
 
+[[package]]
+name = "tracing-opentelemetry"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de"
+dependencies = [
+ "once_cell",
+ "opentelemetry 0.18.0",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-subscriber",
+]
+
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b"
+checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
 dependencies = [
- "ansi_term",
  "matchers",
+ "nu-ansi-term",
  "once_cell",
  "regex",
  "sharded-slab",
@@ -4347,9 +4581,9 @@ version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
 ]
 
 [[package]]
@@ -4381,9 +4615,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
 
 [[package]]
 name = "unicode-normalization"
@@ -4444,21 +4678,11 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
 name = "uuid"
-version = "0.8.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
-dependencies = [
- "getrandom 0.2.7",
- "serde",
-]
-
-[[package]]
-name = "uuid"
-version = "1.1.2"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
+checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83"
 dependencies = [
- "getrandom 0.2.7",
+ "getrandom 0.2.8",
  "serde",
 ]
 
@@ -4538,9 +4762,9 @@ dependencies = [
  "bumpalo",
  "log",
  "once_cell",
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
  "wasm-bindgen-shared",
 ]
 
@@ -4572,9 +4796,9 @@ version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
 dependencies = [
- "proc-macro2 1.0.43",
+ "proc-macro2 1.0.47",
  "quote 1.0.21",
- "syn 1.0.100",
+ "syn 1.0.103",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -4634,9 +4858,9 @@ dependencies = [
 
 [[package]]
 name = "webpki-roots"
-version = "0.22.4"
+version = "0.22.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1c760f0d366a6c24a02ed7816e23e691f5d92291f94d15e836006fd11b04daf"
+checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
 dependencies = [
  "webpki",
 ]
@@ -4689,43 +4913,100 @@ version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
 dependencies = [
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_msvc",
+ "windows_aarch64_msvc 0.36.1",
+ "windows_i686_gnu 0.36.1",
+ "windows_i686_msvc 0.36.1",
+ "windows_x86_64_gnu 0.36.1",
+ "windows_x86_64_msvc 0.36.1",
 ]
 
+[[package]]
+name = "windows-sys"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc 0.42.0",
+ "windows_i686_gnu 0.42.0",
+ "windows_i686_msvc 0.42.0",
+ "windows_x86_64_gnu 0.42.0",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc 0.42.0",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
 
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+
 [[package]]
 name = "winreg"
 version = "0.10.1"
diff --git a/Cargo.toml b/Cargo.toml
index 82962d16..c01d013c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -50,9 +50,10 @@ lemmy_api_common = { version = "=0.16.5", path = "crates/api_common" }
 lemmy_websocket = { version = "=0.16.5", path = "./crates/websocket" }
 lemmy_routes = { version = "=0.16.5", path = "./crates/routes" }
 activitypub_federation = "0.2.3"
-diesel = "2.0.0"
+diesel = "2.0.2"
 diesel_migrations = "2.0.0"
-serde = { version = "1.0.145", features = ["derive"] }
+diesel-async = "0.1.1"
+serde = { version = "1.0.147", features = ["derive"] }
 actix = "0.13.0"
 actix-web = { version = "4.2.1", default-features = false, features = ["macros", "rustls"] }
 tracing = "0.1.36"
diff --git a/api_tests/package.json b/api_tests/package.json
index 48d87399..82d2f0eb 100644
--- a/api_tests/package.json
+++ b/api_tests/package.json
@@ -20,7 +20,7 @@
     "eslint": "^8.25.0",
     "eslint-plugin-prettier": "^4.0.0",
     "jest": "^27.0.6",
-    "lemmy-js-client": "0.17.0-rc.47",
+    "lemmy-js-client": "0.17.0-rc.48",
     "node-fetch": "^2.6.1",
     "prettier": "^2.7.1",
     "reflect-metadata": "^0.1.13",
diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh
index 3356f0a8..afe18e1d 100755
--- a/api_tests/prepare-drone-federation-test.sh
+++ b/api_tests/prepare-drone-federation-test.sh
@@ -31,41 +31,35 @@ killall lemmy_server || true
 echo "$PWD"
 
 echo "start alpha"
-LEMMY_HOSTNAME=lemmy-alpha:8541 \
-  LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_alpha.hjson \
-  LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_alpha" \
-  LEMMY_HOSTNAME="lemmy-alpha:8541" \
-  target/lemmy_server >/tmp/lemmy_alpha.out 2>&1 &
+LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_alpha.hjson \
+LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_alpha" \
+target/lemmy_server >/tmp/lemmy_alpha.out 2>&1 &
 
 echo "start beta"
-LEMMY_HOSTNAME=lemmy-beta:8551 \
-  LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_beta.hjson \
-  LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_beta" \
-  target/lemmy_server >/tmp/lemmy_beta.out 2>&1 &
+LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_beta.hjson \
+LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_beta" \
+target/lemmy_server >/tmp/lemmy_beta.out 2>&1 &
 
 echo "start gamma"
-LEMMY_HOSTNAME=lemmy-gamma:8561 \
-  LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_gamma.hjson \
-  LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_gamma" \
-  target/lemmy_server >/tmp/lemmy_gamma.out 2>&1 &
+LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_gamma.hjson \
+LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_gamma" \
+target/lemmy_server >/tmp/lemmy_gamma.out 2>&1 &
 
 echo "start delta"
 # An instance with only an allowlist for beta
-LEMMY_HOSTNAME=lemmy-delta:8571 \
-  LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_delta.hjson \
-  LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_delta" \
-  target/lemmy_server >/tmp/lemmy_delta.out 2>&1 &
+LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_delta.hjson \
+LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_delta" \
+target/lemmy_server >/tmp/lemmy_delta.out 2>&1 &
 
 echo "start epsilon"
 # An instance who has a blocklist, with lemmy-alpha blocked
-LEMMY_HOSTNAME=lemmy-epsilon:8581 \
-  LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_epsilon.hjson \
-  LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_epsilon" \
-  target/lemmy_server >/tmp/lemmy_epsilon.out 2>&1 &
+LEMMY_CONFIG_LOCATION=./docker/federation/lemmy_epsilon.hjson \
+LEMMY_DATABASE_URL="${LEMMY_DATABASE_URL}/lemmy_epsilon" \
+target/lemmy_server >/tmp/lemmy_epsilon.out 2>&1 &
 
 echo "wait for all instances to start"
-while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8541/api/v3/site')" != "200" ]]; do sleep 1; done
-while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8551/api/v3/site')" != "200" ]]; do sleep 1; done
-while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8561/api/v3/site')" != "200" ]]; do sleep 1; done
-while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8571/api/v3/site')" != "200" ]]; do sleep 1; done
-while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'localhost:8581/api/v3/site')" != "200" ]]; do sleep 1; done
+while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-alpha:8541/api/v3/site')" != "200" ]]; do sleep 1; done
+while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-beta:8551/api/v3/site')" != "200" ]]; do sleep 1; done
+while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-gamma:8561/api/v3/site')" != "200" ]]; do sleep 1; done
+while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-delta:8571/api/v3/site')" != "200" ]]; do sleep 1; done
+while [[ "$(curl -s -o /dev/null -w '%{http_code}' 'lemmy-epsilon:8581/api/v3/site')" != "200" ]]; do sleep 1; done
diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock
index 9797ac69..a6b1eef9 100644
--- a/api_tests/yarn.lock
+++ b/api_tests/yarn.lock
@@ -2373,10 +2373,10 @@ kleur@^3.0.3:
   resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
   integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
 
-lemmy-js-client@0.17.0-rc.47:
-  version "0.17.0-rc.47"
-  resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.47.tgz#6094657d2868767532c0e837a31f9af6273b345b"
-  integrity sha512-Pc1wyr6sX4Z6LS75NVu46WAXeci5G80+Y9ZBXEAmgM+OZGuOCLUq8lAHRvTwr7M0pj0gxo5yP+i3qPVmTPf+EA==
+lemmy-js-client@0.17.0-rc.48:
+  version "0.17.0-rc.48"
+  resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.48.tgz#6085812d4901b7d12b3fca237d8aced7f5210eac"
+  integrity sha512-Lz8Nzq/kczQtDj6STlbhxoEarFHtTCoWcWBabyPs6X6em/pfK/cnZqx1mMn7EaBSDUVQ+WL8UNFjQiqjhR4kww==
 
 leven@^3.1.0:
   version "3.1.0"
diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml
index 09136b43..51c8808c 100644
--- a/crates/api/Cargo.toml
+++ b/crates/api/Cargo.toml
@@ -23,15 +23,19 @@ lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", featur
 lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
 activitypub_federation = "0.2.3"
-diesel = "2.0.0"
+diesel = "2.0.2"
 bcrypt = "0.13.0"
 chrono = { version = "0.4.22", features = ["serde"], default-features = false }
-serde_json = { version = "1.0.85", features = ["preserve_order"] }
-serde = { version = "1.0.145", features = ["derive"] }
+serde_json = { version = "1.0.87", features = ["preserve_order"] }
+serde = { version = "1.0.147", features = ["derive"] }
 actix-web = { version = "4.2.1", default-features = false }
-base64 = "0.13.0"
-uuid = { version = "1.1.2", features = ["serde", "v4"] }
-async-trait = "0.1.57"
+base64 = "0.13.1"
+uuid = { version = "1.2.1", features = ["serde", "v4"] }
+async-trait = "0.1.58"
 captcha = "0.0.9"
-anyhow = "1.0.65"
-tracing = "0.1.36"
+anyhow = "1.0.66"
+tracing = "0.1.37"
+
+[dev-dependencies]
+serial_test = "0.9.0"
+tokio = "1.21.2"
diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs
index 754072ee..6ca87f3c 100644
--- a/crates/api/src/comment/like.rs
+++ b/crates/api/src/comment/like.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, CreateCommentLike},
-  utils::{blocking, check_community_ban, check_downvotes_enabled, get_local_user_view_from_jwt},
+  utils::{check_community_ban, check_downvotes_enabled, get_local_user_view_from_jwt},
 };
 use lemmy_apub::{
   fetcher::post_or_comment::PostOrComment,
@@ -36,7 +36,7 @@ impl Perform for CreateCommentLike {
     websocket_id: Option<ConnectionId>,
   ) -> Result<CommentResponse, LemmyError> {
     let data: &CreateCommentLike = self;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
@@ -46,10 +46,7 @@ impl Perform for CreateCommentLike {
     check_downvotes_enabled(data.score, &local_site)?;
 
     let comment_id = data.comment_id;
-    let orig_comment = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, None)
-    })
-    .await??;
+    let orig_comment = CommentView::read(context.pool(), comment_id, None).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -59,17 +56,10 @@ impl Perform for CreateCommentLike {
     .await?;
 
     // Add parent poster or commenter to recipients
-    let comment_reply = blocking(context.pool(), move |conn| {
-      CommentReply::read_by_comment(conn, comment_id)
-    })
-    .await?;
+    let comment_reply = CommentReply::read_by_comment(context.pool(), comment_id).await;
     if let Ok(reply) = comment_reply {
       let recipient_id = reply.recipient_id;
-      if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
-        LocalUserView::read_person(conn, recipient_id)
-      })
-      .await?
-      {
+      if let Ok(local_recipient) = LocalUserView::read_person(context.pool(), recipient_id).await {
         recipient_ids.push(local_recipient.local_user.id);
       }
     }
@@ -83,10 +73,8 @@ impl Perform for CreateCommentLike {
 
     // Remove any likes first
     let person_id = local_user_view.person.id;
-    blocking(context.pool(), move |conn| {
-      CommentLike::remove(conn, person_id, comment_id)
-    })
-    .await??;
+
+    CommentLike::remove(context.pool(), person_id, comment_id).await?;
 
     // Only add the like if the score isnt 0
     let comment = orig_comment.comment;
@@ -94,9 +82,8 @@ impl Perform for CreateCommentLike {
     let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
     if do_add {
       let like_form2 = like_form.clone();
-      let like = move |conn: &mut _| CommentLike::like(conn, &like_form2);
-      blocking(context.pool(), like)
-        .await?
+      CommentLike::like(context.pool(), &like_form2)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
 
       Vote::send(
diff --git a/crates/api/src/comment/save.rs b/crates/api/src/comment/save.rs
index e1a26d57..647f0ed5 100644
--- a/crates/api/src/comment/save.rs
+++ b/crates/api/src/comment/save.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, SaveComment},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::comment::{CommentSaved, CommentSavedForm},
@@ -32,23 +32,18 @@ impl Perform for SaveComment {
     };
 
     if data.save {
-      let save_comment = move |conn: &mut _| CommentSaved::save(conn, &comment_saved_form);
-      blocking(context.pool(), save_comment)
-        .await?
+      CommentSaved::save(context.pool(), &comment_saved_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_save_comment"))?;
     } else {
-      let unsave_comment = move |conn: &mut _| CommentSaved::unsave(conn, &comment_saved_form);
-      blocking(context.pool(), unsave_comment)
-        .await?
+      CommentSaved::unsave(context.pool(), &comment_saved_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_save_comment"))?;
     }
 
     let comment_id = data.comment_id;
     let person_id = local_user_view.person.id;
-    let comment_view = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, Some(person_id))
-    })
-    .await??;
+    let comment_view = CommentView::read(context.pool(), comment_id, Some(person_id)).await?;
 
     Ok(CommentResponse {
       comment_view,
diff --git a/crates/api/src/comment_report/create.rs b/crates/api/src/comment_report/create.rs
index 5a93fa02..2533aba1 100644
--- a/crates/api/src/comment_report/create.rs
+++ b/crates/api/src/comment_report/create.rs
@@ -3,7 +3,7 @@ use activitypub_federation::core::object_id::ObjectId;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentReportResponse, CreateCommentReport},
-  utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
+  utils::{check_community_ban, get_local_user_view_from_jwt},
 };
 use lemmy_apub::protocol::activities::community::report::Report;
 use lemmy_db_schema::{
@@ -31,17 +31,14 @@ impl Perform for CreateCommentReport {
     let data: &CreateCommentReport = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let reason = self.reason.trim();
     check_report_reason(reason, &local_site)?;
 
     let person_id = local_user_view.person.id;
     let comment_id = data.comment_id;
-    let comment_view = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, None)
-    })
-    .await??;
+    let comment_view = CommentView::read(context.pool(), comment_id, None).await?;
 
     check_community_ban(person_id, comment_view.community.id, context.pool()).await?;
 
@@ -52,16 +49,11 @@ impl Perform for CreateCommentReport {
       reason: reason.to_owned(),
     };
 
-    let report = blocking(context.pool(), move |conn| {
-      CommentReport::report(conn, &report_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
+    let report = CommentReport::report(context.pool(), &report_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
 
-    let comment_report_view = blocking(context.pool(), move |conn| {
-      CommentReportView::read(conn, report.id, person_id)
-    })
-    .await??;
+    let comment_report_view = CommentReportView::read(context.pool(), report.id, person_id).await?;
 
     let res = CommentReportResponse {
       comment_report_view,
diff --git a/crates/api/src/comment_report/list.rs b/crates/api/src/comment_report/list.rs
index 3a924aea..4a9041e9 100644
--- a/crates/api/src/comment_report/list.rs
+++ b/crates/api/src/comment_report/list.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{ListCommentReports, ListCommentReportsResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views::comment_report_view::CommentReportQuery;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -31,19 +31,17 @@ impl Perform for ListCommentReports {
 
     let page = data.page;
     let limit = data.limit;
-    let comment_reports = blocking(context.pool(), move |conn| {
-      CommentReportQuery::builder()
-        .conn(conn)
-        .my_person_id(person_id)
-        .admin(admin)
-        .community_id(community_id)
-        .unresolved_only(unresolved_only)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let comment_reports = CommentReportQuery::builder()
+      .pool(context.pool())
+      .my_person_id(person_id)
+      .admin(admin)
+      .community_id(community_id)
+      .unresolved_only(unresolved_only)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     let res = ListCommentReportsResponse { comment_reports };
 
diff --git a/crates/api/src/comment_report/resolve.rs b/crates/api/src/comment_report/resolve.rs
index c0b8a400..8055e948 100644
--- a/crates/api/src/comment_report/resolve.rs
+++ b/crates/api/src/comment_report/resolve.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentReportResponse, ResolveCommentReport},
-  utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
+  utils::{get_local_user_view_from_jwt, is_mod_or_admin},
 };
 use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
 use lemmy_db_views::structs::CommentReportView;
@@ -26,32 +26,23 @@ impl Perform for ResolveCommentReport {
 
     let report_id = data.report_id;
     let person_id = local_user_view.person.id;
-    let report = blocking(context.pool(), move |conn| {
-      CommentReportView::read(conn, report_id, person_id)
-    })
-    .await??;
+    let report = CommentReportView::read(context.pool(), report_id, person_id).await?;
 
     let person_id = local_user_view.person.id;
     is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
 
-    let resolved = data.resolved;
-    let resolve_fun = move |conn: &mut _| {
-      if resolved {
-        CommentReport::resolve(conn, report_id, person_id)
-      } else {
-        CommentReport::unresolve(conn, report_id, person_id)
-      }
-    };
-
-    blocking(context.pool(), resolve_fun)
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    if data.resolved {
+      CommentReport::resolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    } else {
+      CommentReport::unresolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    }
 
     let report_id = data.report_id;
-    let comment_report_view = blocking(context.pool(), move |conn| {
-      CommentReportView::read(conn, report_id, person_id)
-    })
-    .await??;
+    let comment_report_view = CommentReportView::read(context.pool(), report_id, person_id).await?;
 
     let res = CommentReportResponse {
       comment_report_view,
diff --git a/crates/api/src/community/add_mod.rs b/crates/api/src/community/add_mod.rs
index f0c5ed17..ff54edda 100644
--- a/crates/api/src/community/add_mod.rs
+++ b/crates/api/src/community/add_mod.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{AddModToCommunity, AddModToCommunityResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
+  utils::{get_local_user_view_from_jwt, is_mod_or_admin},
 };
 use lemmy_apub::{
   objects::{community::ApubCommunity, person::ApubPerson},
@@ -38,10 +38,7 @@ impl Perform for AddModToCommunity {
 
     // Verify that only mods or admins can add mod
     is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
     if local_user_view.person.admin && !community.local {
       return Err(LemmyError::from_message("not_a_moderator"));
     }
@@ -52,14 +49,12 @@ impl Perform for AddModToCommunity {
       person_id: data.person_id,
     };
     if data.added {
-      let join = move |conn: &mut _| CommunityModerator::join(conn, &community_moderator_form);
-      blocking(context.pool(), join)
-        .await?
+      CommunityModerator::join(context.pool(), &community_moderator_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_moderator_already_exists"))?;
     } else {
-      let leave = move |conn: &mut _| CommunityModerator::leave(conn, &community_moderator_form);
-      blocking(context.pool(), leave)
-        .await?
+      CommunityModerator::leave(context.pool(), &community_moderator_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_moderator_already_exists"))?;
     }
 
@@ -70,18 +65,12 @@ impl Perform for AddModToCommunity {
       community_id: data.community_id,
       removed: Some(!data.added),
     };
-    blocking(context.pool(), move |conn| {
-      ModAddCommunity::create(conn, &form)
-    })
-    .await??;
+
+    ModAddCommunity::create(context.pool(), &form).await?;
 
     // Send to federated instances
     let updated_mod_id = data.person_id;
-    let updated_mod: ApubPerson = blocking(context.pool(), move |conn| {
-      Person::read(conn, updated_mod_id)
-    })
-    .await??
-    .into();
+    let updated_mod: ApubPerson = Person::read(context.pool(), updated_mod_id).await?.into();
     let community: ApubCommunity = community.into();
     if data.added {
       AddMod::send(
@@ -104,10 +93,7 @@ impl Perform for AddModToCommunity {
     // Note: in case a remote mod is added, this returns the old moderators list, it will only get
     //       updated once we receive an activity from the community (like `Announce/Add/Moderator`)
     let community_id = data.community_id;
-    let moderators = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await??;
+    let moderators = CommunityModeratorView::for_community(context.pool(), community_id).await?;
 
     let res = AddModToCommunityResponse { moderators };
     context.chat_server().do_send(SendCommunityRoomMessage {
diff --git a/crates/api/src/community/ban.rs b/crates/api/src/community/ban.rs
index 9ea0c5c9..3b3de914 100644
--- a/crates/api/src/community/ban.rs
+++ b/crates/api/src/community/ban.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{BanFromCommunity, BanFromCommunityResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
+  utils::{get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
 };
 use lemmy_apub::{
   activities::block::SiteOrCommunity,
@@ -55,21 +55,12 @@ impl Perform for BanFromCommunity {
       expires: Some(expires),
     };
 
-    let community: ApubCommunity = blocking(context.pool(), move |conn: &mut _| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
-    let banned_person: ApubPerson = blocking(context.pool(), move |conn: &mut _| {
-      Person::read(conn, banned_person_id)
-    })
-    .await??
-    .into();
+    let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
+    let banned_person: ApubPerson = Person::read(context.pool(), banned_person_id).await?.into();
 
     if data.ban {
-      let ban = move |conn: &mut _| CommunityPersonBan::ban(conn, &community_user_ban_form);
-      blocking(context.pool(), ban)
-        .await?
+      CommunityPersonBan::ban(context.pool(), &community_user_ban_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
 
       // Also unsubscribe them from the community, if they are subscribed
@@ -78,11 +69,10 @@ impl Perform for BanFromCommunity {
         person_id: banned_person_id,
         pending: false,
       };
-      blocking(context.pool(), move |conn: &mut _| {
-        CommunityFollower::unfollow(conn, &community_follower_form)
-      })
-      .await?
-      .ok();
+
+      CommunityFollower::unfollow(context.pool(), &community_follower_form)
+        .await
+        .ok();
 
       BlockUser::send(
         &SiteOrCommunity::Community(community),
@@ -95,9 +85,8 @@ impl Perform for BanFromCommunity {
       )
       .await?;
     } else {
-      let unban = move |conn: &mut _| CommunityPersonBan::unban(conn, &community_user_ban_form);
-      blocking(context.pool(), unban)
-        .await?
+      CommunityPersonBan::unban(context.pool(), &community_user_ban_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
       UndoBlockUser::send(
         &SiteOrCommunity::Community(community),
@@ -123,16 +112,11 @@ impl Perform for BanFromCommunity {
       banned: Some(data.ban),
       expires,
     };
-    blocking(context.pool(), move |conn| {
-      ModBanFromCommunity::create(conn, &form)
-    })
-    .await??;
+
+    ModBanFromCommunity::create(context.pool(), &form).await?;
 
     let person_id = data.person_id;
-    let person_view = blocking(context.pool(), move |conn| {
-      PersonViewSafe::read(conn, person_id)
-    })
-    .await??;
+    let person_view = PersonViewSafe::read(context.pool(), person_id).await?;
 
     let res = BanFromCommunityResponse {
       person_view,
diff --git a/crates/api/src/community/block.rs b/crates/api/src/community/block.rs
index 5f01ac3d..5aaeb831 100644
--- a/crates/api/src/community/block.rs
+++ b/crates/api/src/community/block.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{BlockCommunity, BlockCommunityResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_apub::protocol::activities::following::undo_follow::UndoFollowCommunity;
 use lemmy_db_schema::{
@@ -38,9 +38,8 @@ impl Perform for BlockCommunity {
     };
 
     if data.block {
-      let block = move |conn: &mut _| CommunityBlock::block(conn, &community_block_form);
-      blocking(context.pool(), block)
-        .await?
+      CommunityBlock::block(context.pool(), &community_block_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_block_already_exists"))?;
 
       // Also, unfollow the community, and send a federated unfollow
@@ -49,27 +48,19 @@ impl Perform for BlockCommunity {
         person_id,
         pending: false,
       };
-      blocking(context.pool(), move |conn: &mut _| {
-        CommunityFollower::unfollow(conn, &community_follower_form)
-      })
-      .await?
-      .ok();
-      let community = blocking(context.pool(), move |conn| {
-        Community::read(conn, community_id)
-      })
-      .await??;
+
+      CommunityFollower::unfollow(context.pool(), &community_follower_form)
+        .await
+        .ok();
+      let community = Community::read(context.pool(), community_id).await?;
       UndoFollowCommunity::send(&local_user_view.person.into(), &community.into(), context).await?;
     } else {
-      let unblock = move |conn: &mut _| CommunityBlock::unblock(conn, &community_block_form);
-      blocking(context.pool(), unblock)
-        .await?
+      CommunityBlock::unblock(context.pool(), &community_block_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_block_already_exists"))?;
     }
 
-    let community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, Some(person_id))
-    })
-    .await??;
+    let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
 
     Ok(BlockCommunityResponse {
       blocked: data.block,
diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs
index 7a5e3198..8a68646e 100644
--- a/crates/api/src/community/follow.rs
+++ b/crates/api/src/community/follow.rs
@@ -2,12 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, FollowCommunity},
-  utils::{
-    blocking,
-    check_community_ban,
-    check_community_deleted_or_removed,
-    get_local_user_view_from_jwt,
-  },
+  utils::{check_community_ban, check_community_deleted_or_removed, get_local_user_view_from_jwt},
 };
 use lemmy_apub::{
   objects::community::ApubCommunity,
@@ -39,11 +34,7 @@ impl Perform for FollowCommunity {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let community_id = data.community_id;
-    let community: ApubCommunity = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
+    let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
     let community_follower_form = CommunityFollowerForm {
       community_id: data.community_id,
       person_id: local_user_view.person.id,
@@ -55,15 +46,12 @@ impl Perform for FollowCommunity {
         check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
         check_community_deleted_or_removed(community_id, context.pool()).await?;
 
-        let follow = move |conn: &mut _| CommunityFollower::follow(conn, &community_follower_form);
-        blocking(context.pool(), follow)
-          .await?
+        CommunityFollower::follow(context.pool(), &community_follower_form)
+          .await
           .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
       } else {
-        let unfollow =
-          move |conn: &mut _| CommunityFollower::unfollow(conn, &community_follower_form);
-        blocking(context.pool(), unfollow)
-          .await?
+        CommunityFollower::unfollow(context.pool(), &community_follower_form)
+          .await
           .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
       }
     } else if data.follow {
@@ -74,19 +62,14 @@ impl Perform for FollowCommunity {
     } else {
       UndoFollowCommunity::send(&local_user_view.person.clone().into(), &community, context)
         .await?;
-      let unfollow =
-        move |conn: &mut _| CommunityFollower::unfollow(conn, &community_follower_form);
-      blocking(context.pool(), unfollow)
-        .await?
+      CommunityFollower::unfollow(context.pool(), &community_follower_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
     }
 
     let community_id = data.community_id;
     let person_id = local_user_view.person.id;
-    let community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, Some(person_id))
-    })
-    .await??;
+    let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
 
     Ok(Self::Response { community_view })
   }
diff --git a/crates/api/src/community/hide.rs b/crates/api/src/community/hide.rs
index 278d492d..111a89d0 100644
--- a/crates/api/src/community/hide.rs
+++ b/crates/api/src/community/hide.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, HideCommunity},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
 use lemmy_db_schema::{
@@ -44,16 +44,11 @@ impl Perform for HideCommunity {
     };
 
     let community_id = data.community_id;
-    let updated_community = blocking(context.pool(), move |conn| {
-      Community::update(conn, community_id, &community_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community_hidden_status"))?;
+    let updated_community = Community::update(context.pool(), community_id, &community_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community_hidden_status"))?;
 
-    blocking(context.pool(), move |conn| {
-      ModHideCommunity::create(conn, &mod_hide_community_form)
-    })
-    .await??;
+    ModHideCommunity::create(context.pool(), &mod_hide_community_form).await?;
 
     UpdateCommunity::send(
       updated_community.into(),
diff --git a/crates/api/src/community/transfer.rs b/crates/api/src/community/transfer.rs
index 36664108..5da0d8e3 100644
--- a/crates/api/src/community/transfer.rs
+++ b/crates/api/src/community/transfer.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use anyhow::Context;
 use lemmy_api_common::{
   community::{GetCommunityResponse, TransferCommunity},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::{
@@ -32,14 +32,12 @@ impl Perform for TransferCommunity {
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
-    let admins = blocking(context.pool(), PersonViewSafe::admins).await??;
+    let admins = PersonViewSafe::admins(context.pool()).await?;
 
     // Fetch the community mods
     let community_id = data.community_id;
-    let mut community_mods = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await??;
+    let mut community_mods =
+      CommunityModeratorView::for_community(context.pool(), community_id).await?;
 
     // Make sure transferrer is either the top community mod, or an admin
     if local_user_view.person.id != community_mods[0].moderator.id
@@ -62,10 +60,8 @@ impl Perform for TransferCommunity {
 
     // Delete all the mods
     let community_id = data.community_id;
-    blocking(context.pool(), move |conn| {
-      CommunityModerator::delete_for_community(conn, community_id)
-    })
-    .await??;
+
+    CommunityModerator::delete_for_community(context.pool(), community_id).await?;
 
     // TODO: this should probably be a bulk operation
     // Re-add the mods, in the new order
@@ -75,9 +71,8 @@ impl Perform for TransferCommunity {
         person_id: cmod.moderator.id,
       };
 
-      let join = move |conn: &mut _| CommunityModerator::join(conn, &community_moderator_form);
-      blocking(context.pool(), join)
-        .await?
+      CommunityModerator::join(context.pool(), &community_moderator_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "community_moderator_already_exists"))?;
     }
 
@@ -88,25 +83,19 @@ impl Perform for TransferCommunity {
       community_id: data.community_id,
       removed: Some(false),
     };
-    blocking(context.pool(), move |conn| {
-      ModTransferCommunity::create(conn, &form)
-    })
-    .await??;
+
+    ModTransferCommunity::create(context.pool(), &form).await?;
 
     let community_id = data.community_id;
     let person_id = local_user_view.person.id;
-    let community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, Some(person_id))
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
+    let community_view = CommunityView::read(context.pool(), community_id, Some(person_id))
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
 
     let community_id = data.community_id;
-    let moderators = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
+    let moderators = CommunityModeratorView::for_community(context.pool(), community_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
 
     // Return the jwt
     Ok(GetCommunityResponse {
diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs
index 595ab10f..40026d89 100644
--- a/crates/api/src/lib.rs
+++ b/crates/api/src/lib.rs
@@ -253,17 +253,19 @@ mod tests {
       secret::Secret,
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use lemmy_utils::{claims::Claims, settings::SETTINGS};
+  use serial_test::serial;
 
-  #[test]
-  fn test_should_not_validate_user_token_after_password_change() {
-    let conn = &mut establish_unpooled_connection();
-    let secret = Secret::init(conn).unwrap();
+  #[tokio::test]
+  #[serial]
+  async fn test_should_not_validate_user_token_after_password_change() {
+    let pool = &build_db_pool_for_tests().await;
+    let secret = Secret::init(pool).await.unwrap();
     let settings = &SETTINGS.to_owned();
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("Gerry9812".into())
@@ -271,14 +273,14 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_person.id)
       .password_encrypted("123456".to_string())
       .build();
 
-    let inserted_local_user = LocalUser::create(conn, &local_user_form).unwrap();
+    let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
 
     let jwt = Claims::jwt(
       inserted_local_user.id.0,
@@ -292,11 +294,13 @@ mod tests {
 
     // The check should fail, since the validator time is now newer than the jwt issue time
     let updated_local_user =
-      LocalUser::update_password(conn, inserted_local_user.id, "password111").unwrap();
+      LocalUser::update_password(pool, inserted_local_user.id, "password111")
+        .await
+        .unwrap();
     let check_after = check_validator_time(&updated_local_user.validator_time, &claims);
     assert!(check_after.is_err());
 
-    let num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, num_deleted);
   }
 }
diff --git a/crates/api/src/local_user/add_admin.rs b/crates/api/src/local_user/add_admin.rs
index 2561906e..ceca80f9 100644
--- a/crates/api/src/local_user/add_admin.rs
+++ b/crates/api/src/local_user/add_admin.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{AddAdmin, AddAdminResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::{
   source::{
@@ -34,14 +34,12 @@ impl Perform for AddAdmin {
 
     let added = data.added;
     let added_person_id = data.person_id;
-    let added_admin = blocking(context.pool(), move |conn| {
-      Person::update(
-        conn,
-        added_person_id,
-        &PersonUpdateForm::builder().admin(Some(added)).build(),
-      )
-    })
-    .await?
+    let added_admin = Person::update(
+      context.pool(),
+      added_person_id,
+      &PersonUpdateForm::builder().admin(Some(added)).build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_user"))?;
 
     // Mod tables
@@ -51,9 +49,9 @@ impl Perform for AddAdmin {
       removed: Some(!data.added),
     };
 
-    blocking(context.pool(), move |conn| ModAdd::create(conn, &form)).await??;
+    ModAdd::create(context.pool(), &form).await?;
 
-    let admins = blocking(context.pool(), PersonViewSafe::admins).await??;
+    let admins = PersonViewSafe::admins(context.pool()).await?;
 
     let res = AddAdminResponse { admins };
 
diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs
index f9dc83e0..27814192 100644
--- a/crates/api/src/local_user/ban_person.rs
+++ b/crates/api/src/local_user/ban_person.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{BanPerson, BanPersonResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin, remove_user_data},
+  utils::{get_local_user_view_from_jwt, is_admin, remove_user_data},
 };
 use lemmy_apub::{
   activities::block::SiteOrCommunity,
@@ -41,17 +41,15 @@ impl Perform for BanPerson {
     let banned_person_id = data.person_id;
     let expires = data.expires.map(naive_from_unix);
 
-    let person = blocking(context.pool(), move |conn| {
-      Person::update(
-        conn,
-        banned_person_id,
-        &PersonUpdateForm::builder()
-          .banned(Some(ban))
-          .ban_expires(Some(expires))
-          .build(),
-      )
-    })
-    .await?
+    let person = Person::update(
+      context.pool(),
+      banned_person_id,
+      &PersonUpdateForm::builder()
+        .banned(Some(ban))
+        .ban_expires(Some(expires))
+        .build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_user"))?;
 
     // Remove their data if that's desired
@@ -75,20 +73,12 @@ impl Perform for BanPerson {
       expires,
     };
 
-    blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??;
+    ModBan::create(context.pool(), &form).await?;
 
     let person_id = data.person_id;
-    let person_view = blocking(context.pool(), move |conn| {
-      PersonViewSafe::read(conn, person_id)
-    })
-    .await??;
+    let person_view = PersonViewSafe::read(context.pool(), person_id).await?;
 
-    let site = SiteOrCommunity::Site(
-      blocking(context.pool(), SiteView::read_local)
-        .await??
-        .site
-        .into(),
-    );
+    let site = SiteOrCommunity::Site(SiteView::read_local(context.pool()).await?.site.into());
     // if the action affects a local user, federate to other instances
     if person.local {
       if ban {
diff --git a/crates/api/src/local_user/block.rs b/crates/api/src/local_user/block.rs
index 3f1b36f2..44bd668f 100644
--- a/crates/api/src/local_user/block.rs
+++ b/crates/api/src/local_user/block.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{BlockPerson, BlockPersonResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::person_block::{PersonBlock, PersonBlockForm},
@@ -39,24 +39,19 @@ impl Perform for BlockPerson {
       target_id,
     };
 
-    let target_person_view = blocking(context.pool(), move |conn| {
-      PersonViewSafe::read(conn, target_id)
-    })
-    .await??;
+    let target_person_view = PersonViewSafe::read(context.pool(), target_id).await?;
 
     if target_person_view.person.admin {
       return Err(LemmyError::from_message("cant_block_admin"));
     }
 
     if data.block {
-      let block = move |conn: &mut _| PersonBlock::block(conn, &person_block_form);
-      blocking(context.pool(), block)
-        .await?
+      PersonBlock::block(context.pool(), &person_block_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "person_block_already_exists"))?;
     } else {
-      let unblock = move |conn: &mut _| PersonBlock::unblock(conn, &person_block_form);
-      blocking(context.pool(), unblock)
-        .await?
+      PersonBlock::unblock(context.pool(), &person_block_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "person_block_already_exists"))?;
     }
 
diff --git a/crates/api/src/local_user/change_password.rs b/crates/api/src/local_user/change_password.rs
index 6143fc4f..f13ff9c9 100644
--- a/crates/api/src/local_user/change_password.rs
+++ b/crates/api/src/local_user/change_password.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use bcrypt::verify;
 use lemmy_api_common::{
   person::{ChangePassword, LoginResponse},
-  utils::{blocking, get_local_user_view_from_jwt, password_length_check},
+  utils::{get_local_user_view_from_jwt, password_length_check},
 };
 use lemmy_db_schema::source::local_user::LocalUser;
 use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};
@@ -42,10 +42,8 @@ impl Perform for ChangePassword {
 
     let local_user_id = local_user_view.local_user.id;
     let new_password = data.new_password.to_owned();
-    let updated_local_user = blocking(context.pool(), move |conn| {
-      LocalUser::update_password(conn, local_user_id, &new_password)
-    })
-    .await??;
+    let updated_local_user =
+      LocalUser::update_password(context.pool(), local_user_id, &new_password).await?;
 
     // Return the jwt
     Ok(LoginResponse {
diff --git a/crates/api/src/local_user/change_password_after_reset.rs b/crates/api/src/local_user/change_password_after_reset.rs
index cc4c7400..2086a275 100644
--- a/crates/api/src/local_user/change_password_after_reset.rs
+++ b/crates/api/src/local_user/change_password_after_reset.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{LoginResponse, PasswordChangeAfterReset},
-  utils::{blocking, password_length_check},
+  utils::password_length_check,
 };
 use lemmy_db_schema::source::{
   local_user::LocalUser,
@@ -25,10 +25,9 @@ impl Perform for PasswordChangeAfterReset {
 
     // Fetch the user_id from the token
     let token = data.token.clone();
-    let local_user_id = blocking(context.pool(), move |conn| {
-      PasswordResetRequest::read_from_token(conn, &token).map(|p| p.local_user_id)
-    })
-    .await??;
+    let local_user_id = PasswordResetRequest::read_from_token(context.pool(), &token)
+      .await
+      .map(|p| p.local_user_id)?;
 
     password_length_check(&data.password)?;
 
@@ -39,11 +38,9 @@ impl Perform for PasswordChangeAfterReset {
 
     // Update the user with the new password
     let password = data.password.clone();
-    let updated_local_user = blocking(context.pool(), move |conn| {
-      LocalUser::update_password(conn, local_user_id, &password)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_user"))?;
+    let updated_local_user = LocalUser::update_password(context.pool(), local_user_id, &password)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_user"))?;
 
     // Return the jwt
     Ok(LoginResponse {
diff --git a/crates/api/src/local_user/get_captcha.rs b/crates/api/src/local_user/get_captcha.rs
index 1d2511f5..c6063efc 100644
--- a/crates/api/src/local_user/get_captcha.rs
+++ b/crates/api/src/local_user/get_captcha.rs
@@ -2,10 +2,7 @@ use crate::{captcha_as_wav_base64, Perform};
 use actix_web::web::Data;
 use captcha::{gen, Difficulty};
 use chrono::Duration;
-use lemmy_api_common::{
-  person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse},
-  utils::blocking,
-};
+use lemmy_api_common::person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse};
 use lemmy_db_schema::{source::local_site::LocalSite, utils::naive_now};
 use lemmy_utils::{error::LemmyError, ConnectionId};
 use lemmy_websocket::{messages::CaptchaItem, LemmyContext};
@@ -20,7 +17,7 @@ impl Perform for GetCaptcha {
     context: &Data<LemmyContext>,
     _websocket_id: Option<ConnectionId>,
   ) -> Result<Self::Response, LemmyError> {
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     if !local_site.captcha_enabled {
       return Ok(GetCaptchaResponse { ok: None });
diff --git a/crates/api/src/local_user/list_banned.rs b/crates/api/src/local_user/list_banned.rs
index 5423bdbe..16df72cc 100644
--- a/crates/api/src/local_user/list_banned.rs
+++ b/crates/api/src/local_user/list_banned.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{BannedPersonsResponse, GetBannedPersons},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_views_actor::structs::PersonViewSafe;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -24,7 +24,7 @@ impl Perform for GetBannedPersons {
     // Make sure user is an admin
     is_admin(&local_user_view)?;
 
-    let banned = blocking(context.pool(), PersonViewSafe::banned).await??;
+    let banned = PersonViewSafe::banned(context.pool()).await?;
 
     let res = Self::Response { banned };
 
diff --git a/crates/api/src/local_user/login.rs b/crates/api/src/local_user/login.rs
index 990424c0..61354387 100644
--- a/crates/api/src/local_user/login.rs
+++ b/crates/api/src/local_user/login.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use bcrypt::verify;
 use lemmy_api_common::{
   person::{Login, LoginResponse},
-  utils::{blocking, check_registration_application, check_user_valid},
+  utils::{check_registration_application, check_user_valid},
 };
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_db_views::structs::LocalUserView;
@@ -22,15 +22,13 @@ impl Perform for Login {
   ) -> Result<LoginResponse, LemmyError> {
     let data: &Login = self;
 
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Fetch that username / email
     let username_or_email = data.username_or_email.clone();
-    let local_user_view = blocking(context.pool(), move |conn| {
-      LocalUserView::find_by_email_or_name(conn, &username_or_email)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?;
+    let local_user_view = LocalUserView::find_by_email_or_name(context.pool(), &username_or_email)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?;
 
     // Verify the password
     let valid: bool = verify(
diff --git a/crates/api/src/local_user/notifications/list_mentions.rs b/crates/api/src/local_user/notifications/list_mentions.rs
index b331012b..d231f718 100644
--- a/crates/api/src/local_user/notifications/list_mentions.rs
+++ b/crates/api/src/local_user/notifications/list_mentions.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetPersonMentions, GetPersonMentionsResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views_actor::person_mention_view::PersonMentionQuery;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -29,20 +29,18 @@ impl Perform for GetPersonMentions {
     let person_id = Some(local_user_view.person.id);
     let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts);
 
-    let mentions = blocking(context.pool(), move |conn| {
-      PersonMentionQuery::builder()
-        .conn(conn)
-        .recipient_id(person_id)
-        .my_person_id(person_id)
-        .sort(sort)
-        .unread_only(unread_only)
-        .show_bot_accounts(show_bot_accounts)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let mentions = PersonMentionQuery::builder()
+      .pool(context.pool())
+      .recipient_id(person_id)
+      .my_person_id(person_id)
+      .sort(sort)
+      .unread_only(unread_only)
+      .show_bot_accounts(show_bot_accounts)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     Ok(GetPersonMentionsResponse { mentions })
   }
diff --git a/crates/api/src/local_user/notifications/list_replies.rs b/crates/api/src/local_user/notifications/list_replies.rs
index 9a92f625..10222998 100644
--- a/crates/api/src/local_user/notifications/list_replies.rs
+++ b/crates/api/src/local_user/notifications/list_replies.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetReplies, GetRepliesResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -29,20 +29,18 @@ impl Perform for GetReplies {
     let person_id = Some(local_user_view.person.id);
     let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts);
 
-    let replies = blocking(context.pool(), move |conn| {
-      CommentReplyQuery::builder()
-        .conn(conn)
-        .recipient_id(person_id)
-        .my_person_id(person_id)
-        .sort(sort)
-        .unread_only(unread_only)
-        .show_bot_accounts(show_bot_accounts)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let replies = CommentReplyQuery::builder()
+      .pool(context.pool())
+      .recipient_id(person_id)
+      .my_person_id(person_id)
+      .sort(sort)
+      .unread_only(unread_only)
+      .show_bot_accounts(show_bot_accounts)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     Ok(GetRepliesResponse { replies })
   }
diff --git a/crates/api/src/local_user/notifications/mark_all_read.rs b/crates/api/src/local_user/notifications/mark_all_read.rs
index b50f87c3..3b8ad0f4 100644
--- a/crates/api/src/local_user/notifications/mark_all_read.rs
+++ b/crates/api/src/local_user/notifications/mark_all_read.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetRepliesResponse, MarkAllAsRead},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::source::{
   comment_reply::CommentReply,
@@ -28,25 +28,19 @@ impl Perform for MarkAllAsRead {
     let person_id = local_user_view.person.id;
 
     // Mark all comment_replies as read
-    blocking(context.pool(), move |conn| {
-      CommentReply::mark_all_as_read(conn, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
+    CommentReply::mark_all_as_read(context.pool(), person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     // Mark all user mentions as read
-    blocking(context.pool(), move |conn| {
-      PersonMention::mark_all_as_read(conn, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
+    PersonMention::mark_all_as_read(context.pool(), person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     // Mark all private_messages as read
-    blocking(context.pool(), move |conn| {
-      PrivateMessage::mark_all_as_read(conn, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
+    PrivateMessage::mark_all_as_read(context.pool(), person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
 
     Ok(GetRepliesResponse { replies: vec![] })
   }
diff --git a/crates/api/src/local_user/notifications/mark_mention_read.rs b/crates/api/src/local_user/notifications/mark_mention_read.rs
index 134b4311..c42e294a 100644
--- a/crates/api/src/local_user/notifications/mark_mention_read.rs
+++ b/crates/api/src/local_user/notifications/mark_mention_read.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{MarkPersonMentionAsRead, PersonMentionResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::person_mention::{PersonMention, PersonMentionUpdateForm},
@@ -27,10 +27,7 @@ impl Perform for MarkPersonMentionAsRead {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let person_mention_id = data.person_mention_id;
-    let read_person_mention = blocking(context.pool(), move |conn| {
-      PersonMention::read(conn, person_mention_id)
-    })
-    .await??;
+    let read_person_mention = PersonMention::read(context.pool(), person_mention_id).await?;
 
     if local_user_view.person.id != read_person_mention.recipient_id {
       return Err(LemmyError::from_message("couldnt_update_comment"));
@@ -38,18 +35,18 @@ impl Perform for MarkPersonMentionAsRead {
 
     let person_mention_id = read_person_mention.id;
     let read = Some(data.read);
-    blocking(context.pool(), move |conn| {
-      PersonMention::update(conn, person_mention_id, &PersonMentionUpdateForm { read })
-    })
-    .await?
+    PersonMention::update(
+      context.pool(),
+      person_mention_id,
+      &PersonMentionUpdateForm { read },
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     let person_mention_id = read_person_mention.id;
     let person_id = local_user_view.person.id;
-    let person_mention_view = blocking(context.pool(), move |conn| {
-      PersonMentionView::read(conn, person_mention_id, Some(person_id))
-    })
-    .await??;
+    let person_mention_view =
+      PersonMentionView::read(context.pool(), person_mention_id, Some(person_id)).await?;
 
     Ok(PersonMentionResponse {
       person_mention_view,
diff --git a/crates/api/src/local_user/notifications/mark_reply_read.rs b/crates/api/src/local_user/notifications/mark_reply_read.rs
index e270d547..2ec5fd80 100644
--- a/crates/api/src/local_user/notifications/mark_reply_read.rs
+++ b/crates/api/src/local_user/notifications/mark_reply_read.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{CommentReplyResponse, MarkCommentReplyAsRead},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::comment_reply::{CommentReply, CommentReplyUpdateForm},
@@ -27,10 +27,7 @@ impl Perform for MarkCommentReplyAsRead {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let comment_reply_id = data.comment_reply_id;
-    let read_comment_reply = blocking(context.pool(), move |conn| {
-      CommentReply::read(conn, comment_reply_id)
-    })
-    .await??;
+    let read_comment_reply = CommentReply::read(context.pool(), comment_reply_id).await?;
 
     if local_user_view.person.id != read_comment_reply.recipient_id {
       return Err(LemmyError::from_message("couldnt_update_comment"));
@@ -38,18 +35,19 @@ impl Perform for MarkCommentReplyAsRead {
 
     let comment_reply_id = read_comment_reply.id;
     let read = Some(data.read);
-    blocking(context.pool(), move |conn| {
-      CommentReply::update(conn, comment_reply_id, &CommentReplyUpdateForm { read })
-    })
-    .await?
+
+    CommentReply::update(
+      context.pool(),
+      comment_reply_id,
+      &CommentReplyUpdateForm { read },
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     let comment_reply_id = read_comment_reply.id;
     let person_id = local_user_view.person.id;
-    let comment_reply_view = blocking(context.pool(), move |conn| {
-      CommentReplyView::read(conn, comment_reply_id, Some(person_id))
-    })
-    .await??;
+    let comment_reply_view =
+      CommentReplyView::read(context.pool(), comment_reply_id, Some(person_id)).await?;
 
     Ok(CommentReplyResponse { comment_reply_view })
   }
diff --git a/crates/api/src/local_user/notifications/unread_count.rs b/crates/api/src/local_user/notifications/unread_count.rs
index 93307ed5..47d826fd 100644
--- a/crates/api/src/local_user/notifications/unread_count.rs
+++ b/crates/api/src/local_user/notifications/unread_count.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetUnreadCount, GetUnreadCountResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views::structs::PrivateMessageView;
 use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView};
@@ -25,20 +25,12 @@ impl Perform for GetUnreadCount {
 
     let person_id = local_user_view.person.id;
 
-    let replies = blocking(context.pool(), move |conn| {
-      CommentReplyView::get_unread_replies(conn, person_id)
-    })
-    .await??;
+    let replies = CommentReplyView::get_unread_replies(context.pool(), person_id).await?;
 
-    let mentions = blocking(context.pool(), move |conn| {
-      PersonMentionView::get_unread_mentions(conn, person_id)
-    })
-    .await??;
+    let mentions = PersonMentionView::get_unread_mentions(context.pool(), person_id).await?;
 
-    let private_messages = blocking(context.pool(), move |conn| {
-      PrivateMessageView::get_unread_messages(conn, person_id)
-    })
-    .await??;
+    let private_messages =
+      PrivateMessageView::get_unread_messages(context.pool(), person_id).await?;
 
     let res = Self::Response {
       replies,
diff --git a/crates/api/src/local_user/report_count.rs b/crates/api/src/local_user/report_count.rs
index a6556f6c..1372e4ca 100644
--- a/crates/api/src/local_user/report_count.rs
+++ b/crates/api/src/local_user/report_count.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetReportCount, GetReportCountResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView};
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -26,23 +26,14 @@ impl Perform for GetReportCount {
     let admin = local_user_view.person.admin;
     let community_id = data.community_id;
 
-    let comment_reports = blocking(context.pool(), move |conn| {
-      CommentReportView::get_report_count(conn, person_id, admin, community_id)
-    })
-    .await??;
+    let comment_reports =
+      CommentReportView::get_report_count(context.pool(), person_id, admin, community_id).await?;
 
-    let post_reports = blocking(context.pool(), move |conn| {
-      PostReportView::get_report_count(conn, person_id, admin, community_id)
-    })
-    .await??;
+    let post_reports =
+      PostReportView::get_report_count(context.pool(), person_id, admin, community_id).await?;
 
     let private_message_reports = if admin && community_id.is_none() {
-      Some(
-        blocking(context.pool(), move |conn| {
-          PrivateMessageReportView::get_report_count(conn)
-        })
-        .await??,
-      )
+      Some(PrivateMessageReportView::get_report_count(context.pool()).await?)
     } else {
       None
     };
diff --git a/crates/api/src/local_user/reset_password.rs b/crates/api/src/local_user/reset_password.rs
index dbf959e1..078d55ec 100644
--- a/crates/api/src/local_user/reset_password.rs
+++ b/crates/api/src/local_user/reset_password.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{PasswordReset, PasswordResetResponse},
-  utils::{blocking, send_password_reset_email},
+  utils::send_password_reset_email,
 };
 use lemmy_db_views::structs::LocalUserView;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -22,11 +22,9 @@ impl Perform for PasswordReset {
 
     // Fetch that email
     let email = data.email.to_lowercase();
-    let local_user_view = blocking(context.pool(), move |conn| {
-      LocalUserView::find_by_email(conn, &email)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?;
+    let local_user_view = LocalUserView::find_by_email(context.pool(), &email)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_that_username_or_email"))?;
 
     // Email the pure token to the user.
     send_password_reset_email(&local_user_view, context.pool(), context.settings()).await?;
diff --git a/crates/api/src/local_user/save_settings.rs b/crates/api/src/local_user/save_settings.rs
index eac1eef0..232c6a9b 100644
--- a/crates/api/src/local_user/save_settings.rs
+++ b/crates/api/src/local_user/save_settings.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{LoginResponse, SaveUserSettings},
-  utils::{blocking, get_local_user_view_from_jwt, send_verification_email},
+  utils::{get_local_user_view_from_jwt, send_verification_email},
 };
 use lemmy_db_schema::{
   source::{
@@ -35,7 +35,7 @@ impl Perform for SaveUserSettings {
     let data: &SaveUserSettings = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let avatar = diesel_option_overwrite_to_url(&data.avatar)?;
     let banner = diesel_option_overwrite_to_url(&data.banner)?;
@@ -97,17 +97,12 @@ impl Perform for SaveUserSettings {
       .banner(banner)
       .build();
 
-    blocking(context.pool(), move |conn| {
-      Person::update(conn, person_id, &person_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
+    Person::update(context.pool(), person_id, &person_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
 
     if let Some(discussion_languages) = data.discussion_languages.clone() {
-      blocking(context.pool(), move |conn| {
-        LocalUserLanguage::update(conn, discussion_languages, local_user_id)
-      })
-      .await??;
+      LocalUserLanguage::update(context.pool(), discussion_languages, local_user_id).await?;
     }
 
     let local_user_form = LocalUserUpdateForm::builder()
@@ -125,10 +120,7 @@ impl Perform for SaveUserSettings {
       .interface_language(data.interface_language.to_owned())
       .build();
 
-    let local_user_res = blocking(context.pool(), move |conn| {
-      LocalUser::update(conn, local_user_id, &local_user_form)
-    })
-    .await?;
+    let local_user_res = LocalUser::update(context.pool(), local_user_id, &local_user_form).await;
     let updated_local_user = match local_user_res {
       Ok(u) => u,
       Err(e) => {
diff --git a/crates/api/src/local_user/verify_email.rs b/crates/api/src/local_user/verify_email.rs
index e4f43af1..73db4bea 100644
--- a/crates/api/src/local_user/verify_email.rs
+++ b/crates/api/src/local_user/verify_email.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{VerifyEmail, VerifyEmailResponse},
-  utils::{blocking, send_email_verification_success},
+  utils::send_email_verification_success,
 };
 use lemmy_db_schema::{
   source::{
@@ -25,11 +25,9 @@ impl Perform for VerifyEmail {
     _websocket_id: Option<usize>,
   ) -> Result<Self::Response, LemmyError> {
     let token = self.token.clone();
-    let verification = blocking(context.pool(), move |conn| {
-      EmailVerification::read_for_token(conn, &token)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "token_not_found"))?;
+    let verification = EmailVerification::read_for_token(context.pool(), &token)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "token_not_found"))?;
 
     let form = LocalUserUpdateForm::builder()
       // necessary in case this is a new signup
@@ -38,22 +36,14 @@ impl Perform for VerifyEmail {
       .email(Some(Some(verification.email)))
       .build();
     let local_user_id = verification.local_user_id;
-    blocking(context.pool(), move |conn| {
-      LocalUser::update(conn, local_user_id, &form)
-    })
-    .await??;
 
-    let local_user_view = blocking(context.pool(), move |conn| {
-      LocalUserView::read(conn, local_user_id)
-    })
-    .await??;
+    LocalUser::update(context.pool(), local_user_id, &form).await?;
+
+    let local_user_view = LocalUserView::read(context.pool(), local_user_id).await?;
 
     send_email_verification_success(&local_user_view, context.settings())?;
 
-    blocking(context.pool(), move |conn| {
-      EmailVerification::delete_old_tokens_for_local_user(conn, local_user_id)
-    })
-    .await??;
+    EmailVerification::delete_old_tokens_for_local_user(context.pool(), local_user_id).await?;
 
     Ok(VerifyEmailResponse {})
   }
diff --git a/crates/api/src/post/like.rs b/crates/api/src/post/like.rs
index ee29a021..ec2edc33 100644
--- a/crates/api/src/post/like.rs
+++ b/crates/api/src/post/like.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   post::{CreatePostLike, PostResponse},
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     check_downvotes_enabled,
@@ -42,16 +41,14 @@ impl Perform for CreatePostLike {
     let data: &CreatePostLike = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Don't do a downvote if site has downvotes disabled
     check_downvotes_enabled(data.score, &local_site)?;
 
     // Check for a community ban
     let post_id = data.post_id;
-    let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, post_id))
-      .await??
-      .into();
+    let post: ApubPost = Post::read(context.pool(), post_id).await?.into();
 
     check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
     check_community_deleted_or_removed(post.community_id, context.pool()).await?;
@@ -64,10 +61,8 @@ impl Perform for CreatePostLike {
 
     // Remove any likes first
     let person_id = local_user_view.person.id;
-    blocking(context.pool(), move |conn| {
-      PostLike::remove(conn, person_id, post_id)
-    })
-    .await??;
+
+    PostLike::remove(context.pool(), person_id, post_id).await?;
 
     let community_id = post.community_id;
     let object = PostOrComment::Post(Box::new(post));
@@ -76,9 +71,8 @@ impl Perform for CreatePostLike {
     let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
     if do_add {
       let like_form2 = like_form.clone();
-      let like = move |conn: &mut _| PostLike::like(conn, &like_form2);
-      blocking(context.pool(), like)
-        .await?
+      PostLike::like(context.pool(), &like_form2)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_post"))?;
 
       Vote::send(
diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs
index 5ce26c5e..d47088e8 100644
--- a/crates/api/src/post/lock.rs
+++ b/crates/api/src/post/lock.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   post::{LockPost, PostResponse},
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     get_local_user_view_from_jwt,
@@ -39,7 +38,7 @@ impl Perform for LockPost {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let post_id = data.post_id;
-    let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let orig_post = Post::read(context.pool(), post_id).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -60,14 +59,12 @@ impl Perform for LockPost {
     // Update the post
     let post_id = data.post_id;
     let locked = data.locked;
-    let updated_post: ApubPost = blocking(context.pool(), move |conn| {
-      Post::update(
-        conn,
-        post_id,
-        &PostUpdateForm::builder().locked(Some(locked)).build(),
-      )
-    })
-    .await??
+    let updated_post: ApubPost = Post::update(
+      context.pool(),
+      post_id,
+      &PostUpdateForm::builder().locked(Some(locked)).build(),
+    )
+    .await?
     .into();
 
     // Mod tables
@@ -76,7 +73,7 @@ impl Perform for LockPost {
       post_id: data.post_id,
       locked: Some(locked),
     };
-    blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
+    ModLockPost::create(context.pool(), &form).await?;
 
     // apub updates
     CreateOrUpdatePost::send(
diff --git a/crates/api/src/post/mark_read.rs b/crates/api/src/post/mark_read.rs
index 07659ea8..18f86521 100644
--- a/crates/api/src/post/mark_read.rs
+++ b/crates/api/src/post/mark_read.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{MarkPostAsRead, PostResponse},
-  utils::{blocking, get_local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
+  utils::{get_local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
 };
 use lemmy_db_views::structs::PostView;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -33,10 +33,7 @@ impl Perform for MarkPostAsRead {
     }
 
     // Fetch it
-    let post_view = blocking(context.pool(), move |conn| {
-      PostView::read(conn, post_id, Some(person_id))
-    })
-    .await??;
+    let post_view = PostView::read(context.pool(), post_id, Some(person_id)).await?;
 
     let res = Self::Response { post_view };
 
diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs
index ff41581c..0a240f9e 100644
--- a/crates/api/src/post/save.rs
+++ b/crates/api/src/post/save.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{PostResponse, SavePost},
-  utils::{blocking, get_local_user_view_from_jwt, mark_post_as_read},
+  utils::{get_local_user_view_from_jwt, mark_post_as_read},
 };
 use lemmy_db_schema::{
   source::post::{PostSaved, PostSavedForm},
@@ -32,23 +32,18 @@ impl Perform for SavePost {
     };
 
     if data.save {
-      let save = move |conn: &mut _| PostSaved::save(conn, &post_saved_form);
-      blocking(context.pool(), save)
-        .await?
+      PostSaved::save(context.pool(), &post_saved_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_save_post"))?;
     } else {
-      let unsave = move |conn: &mut _| PostSaved::unsave(conn, &post_saved_form);
-      blocking(context.pool(), unsave)
-        .await?
+      PostSaved::unsave(context.pool(), &post_saved_form)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_save_post"))?;
     }
 
     let post_id = data.post_id;
     let person_id = local_user_view.person.id;
-    let post_view = blocking(context.pool(), move |conn| {
-      PostView::read(conn, post_id, Some(person_id))
-    })
-    .await??;
+    let post_view = PostView::read(context.pool(), post_id, Some(person_id)).await?;
 
     // Mark the post as read
     mark_post_as_read(person_id, post_id, context.pool()).await?;
diff --git a/crates/api/src/post/sticky.rs b/crates/api/src/post/sticky.rs
index 629de9d6..ec4c39a8 100644
--- a/crates/api/src/post/sticky.rs
+++ b/crates/api/src/post/sticky.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   post::{PostResponse, StickyPost},
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     get_local_user_view_from_jwt,
@@ -39,7 +38,7 @@ impl Perform for StickyPost {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let post_id = data.post_id;
-    let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let orig_post = Post::read(context.pool(), post_id).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -60,14 +59,12 @@ impl Perform for StickyPost {
     // Update the post
     let post_id = data.post_id;
     let stickied = data.stickied;
-    let updated_post: ApubPost = blocking(context.pool(), move |conn| {
-      Post::update(
-        conn,
-        post_id,
-        &PostUpdateForm::builder().stickied(Some(stickied)).build(),
-      )
-    })
-    .await??
+    let updated_post: ApubPost = Post::update(
+      context.pool(),
+      post_id,
+      &PostUpdateForm::builder().stickied(Some(stickied)).build(),
+    )
+    .await?
     .into();
 
     // Mod tables
@@ -76,10 +73,8 @@ impl Perform for StickyPost {
       post_id: data.post_id,
       stickied: Some(stickied),
     };
-    blocking(context.pool(), move |conn| {
-      ModStickyPost::create(conn, &form)
-    })
-    .await??;
+
+    ModStickyPost::create(context.pool(), &form).await?;
 
     // Apub updates
     // TODO stickied should pry work like locked for ease of use
diff --git a/crates/api/src/post_report/create.rs b/crates/api/src/post_report/create.rs
index 24379f46..ca4113a3 100644
--- a/crates/api/src/post_report/create.rs
+++ b/crates/api/src/post_report/create.rs
@@ -3,7 +3,7 @@ use activitypub_federation::core::object_id::ObjectId;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{CreatePostReport, PostReportResponse},
-  utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
+  utils::{check_community_ban, get_local_user_view_from_jwt},
 };
 use lemmy_apub::protocol::activities::community::report::Report;
 use lemmy_db_schema::{
@@ -31,17 +31,14 @@ impl Perform for CreatePostReport {
     let data: &CreatePostReport = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let reason = self.reason.trim();
     check_report_reason(reason, &local_site)?;
 
     let person_id = local_user_view.person.id;
     let post_id = data.post_id;
-    let post_view = blocking(context.pool(), move |conn| {
-      PostView::read(conn, post_id, None)
-    })
-    .await??;
+    let post_view = PostView::read(context.pool(), post_id, None).await?;
 
     check_community_ban(person_id, post_view.community.id, context.pool()).await?;
 
@@ -54,16 +51,11 @@ impl Perform for CreatePostReport {
       reason: reason.to_owned(),
     };
 
-    let report = blocking(context.pool(), move |conn| {
-      PostReport::report(conn, &report_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
+    let report = PostReport::report(context.pool(), &report_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
 
-    let post_report_view = blocking(context.pool(), move |conn| {
-      PostReportView::read(conn, report.id, person_id)
-    })
-    .await??;
+    let post_report_view = PostReportView::read(context.pool(), report.id, person_id).await?;
 
     let res = PostReportResponse { post_report_view };
 
diff --git a/crates/api/src/post_report/list.rs b/crates/api/src/post_report/list.rs
index 3a4d9dcc..7a79f04b 100644
--- a/crates/api/src/post_report/list.rs
+++ b/crates/api/src/post_report/list.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{ListPostReports, ListPostReportsResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_views::post_report_view::PostReportQuery;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -31,19 +31,17 @@ impl Perform for ListPostReports {
 
     let page = data.page;
     let limit = data.limit;
-    let post_reports = blocking(context.pool(), move |conn| {
-      PostReportQuery::builder()
-        .conn(conn)
-        .my_person_id(person_id)
-        .admin(admin)
-        .community_id(community_id)
-        .unresolved_only(unresolved_only)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let post_reports = PostReportQuery::builder()
+      .pool(context.pool())
+      .my_person_id(person_id)
+      .admin(admin)
+      .community_id(community_id)
+      .unresolved_only(unresolved_only)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     let res = ListPostReportsResponse { post_reports };
 
diff --git a/crates/api/src/post_report/resolve.rs b/crates/api/src/post_report/resolve.rs
index 120a76f1..687bdcce 100644
--- a/crates/api/src/post_report/resolve.rs
+++ b/crates/api/src/post_report/resolve.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{PostReportResponse, ResolvePostReport},
-  utils::{blocking, get_local_user_view_from_jwt, is_mod_or_admin},
+  utils::{get_local_user_view_from_jwt, is_mod_or_admin},
 };
 use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
 use lemmy_db_views::structs::PostReportView;
@@ -26,31 +26,22 @@ impl Perform for ResolvePostReport {
 
     let report_id = data.report_id;
     let person_id = local_user_view.person.id;
-    let report = blocking(context.pool(), move |conn| {
-      PostReportView::read(conn, report_id, person_id)
-    })
-    .await??;
+    let report = PostReportView::read(context.pool(), report_id, person_id).await?;
 
     let person_id = local_user_view.person.id;
     is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
 
-    let resolved = data.resolved;
-    let resolve_fun = move |conn: &mut _| {
-      if resolved {
-        PostReport::resolve(conn, report_id, person_id)
-      } else {
-        PostReport::unresolve(conn, report_id, person_id)
-      }
-    };
-
-    blocking(context.pool(), resolve_fun)
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
-
-    let post_report_view = blocking(context.pool(), move |conn| {
-      PostReportView::read(conn, report_id, person_id)
-    })
-    .await??;
+    if data.resolved {
+      PostReport::resolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    } else {
+      PostReport::unresolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    }
+
+    let post_report_view = PostReportView::read(context.pool(), report_id, person_id).await?;
 
     let res = PostReportResponse { post_report_view };
 
diff --git a/crates/api/src/private_message/mark_read.rs b/crates/api/src/private_message/mark_read.rs
index 6a5737ce..0b7bb676 100644
--- a/crates/api/src/private_message/mark_read.rs
+++ b/crates/api/src/private_message/mark_read.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   source::private_message::{PrivateMessage, PrivateMessageUpdateForm},
@@ -27,10 +27,7 @@ impl Perform for MarkPrivateMessageAsRead {
 
     // Checking permissions
     let private_message_id = data.private_message_id;
-    let orig_private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::read(conn, private_message_id)
-    })
-    .await??;
+    let orig_private_message = PrivateMessage::read(context.pool(), private_message_id).await?;
     if local_user_view.person.id != orig_private_message.recipient_id {
       return Err(LemmyError::from_message("couldnt_update_private_message"));
     }
@@ -38,14 +35,12 @@ impl Perform for MarkPrivateMessageAsRead {
     // Doing the update
     let private_message_id = data.private_message_id;
     let read = data.read;
-    blocking(context.pool(), move |conn| {
-      PrivateMessage::update(
-        conn,
-        private_message_id,
-        &PrivateMessageUpdateForm::builder().read(Some(read)).build(),
-      )
-    })
-    .await?
+    PrivateMessage::update(
+      context.pool(),
+      private_message_id,
+      &PrivateMessageUpdateForm::builder().read(Some(read)).build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
 
     // No need to send an apub update
diff --git a/crates/api/src/private_message_report/create.rs b/crates/api/src/private_message_report/create.rs
index 8e661b79..490fd55b 100644
--- a/crates/api/src/private_message_report/create.rs
+++ b/crates/api/src/private_message_report/create.rs
@@ -2,7 +2,7 @@ use crate::{check_report_reason, Perform};
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::{
   newtypes::CommunityId,
@@ -29,17 +29,14 @@ impl Perform for CreatePrivateMessageReport {
   ) -> Result<Self::Response, LemmyError> {
     let local_user_view =
       get_local_user_view_from_jwt(&self.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let reason = self.reason.trim();
     check_report_reason(reason, &local_site)?;
 
     let person_id = local_user_view.person.id;
     let private_message_id = self.private_message_id;
-    let private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::read(conn, private_message_id)
-    })
-    .await??;
+    let private_message = PrivateMessage::read(context.pool(), private_message_id).await?;
 
     let report_form = PrivateMessageReportForm {
       creator_id: person_id,
@@ -48,16 +45,12 @@ impl Perform for CreatePrivateMessageReport {
       reason: reason.to_owned(),
     };
 
-    let report = blocking(context.pool(), move |conn| {
-      PrivateMessageReport::report(conn, &report_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
+    let report = PrivateMessageReport::report(context.pool(), &report_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
 
-    let private_message_report_view = blocking(context.pool(), move |conn| {
-      PrivateMessageReportView::read(conn, report.id)
-    })
-    .await??;
+    let private_message_report_view =
+      PrivateMessageReportView::read(context.pool(), report.id).await?;
 
     let res = PrivateMessageReportResponse {
       private_message_report_view,
diff --git a/crates/api/src/private_message_report/list.rs b/crates/api/src/private_message_report/list.rs
index 6e530309..0279cb83 100644
--- a/crates/api/src/private_message_report/list.rs
+++ b/crates/api/src/private_message_report/list.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery;
 use lemmy_utils::{error::LemmyError, ConnectionId};
@@ -26,16 +26,14 @@ impl Perform for ListPrivateMessageReports {
     let unresolved_only = self.unresolved_only;
     let page = self.page;
     let limit = self.limit;
-    let private_message_reports = blocking(context.pool(), move |conn| {
-      PrivateMessageReportQuery::builder()
-        .conn(conn)
-        .unresolved_only(unresolved_only)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let private_message_reports = PrivateMessageReportQuery::builder()
+      .pool(context.pool())
+      .unresolved_only(unresolved_only)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     let res = ListPrivateMessageReportsResponse {
       private_message_reports,
diff --git a/crates/api/src/private_message_report/resolve.rs b/crates/api/src/private_message_report/resolve.rs
index 03aab70b..a7af798a 100644
--- a/crates/api/src/private_message_report/resolve.rs
+++ b/crates/api/src/private_message_report/resolve.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::{
   newtypes::CommunityId,
@@ -28,25 +28,20 @@ impl Perform for ResolvePrivateMessageReport {
 
     is_admin(&local_user_view)?;
 
-    let resolved = self.resolved;
     let report_id = self.report_id;
     let person_id = local_user_view.person.id;
-    let resolve_fn = move |conn: &mut _| {
-      if resolved {
-        PrivateMessageReport::resolve(conn, report_id, person_id)
-      } else {
-        PrivateMessageReport::unresolve(conn, report_id, person_id)
-      }
-    };
-
-    blocking(context.pool(), resolve_fn)
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
-
-    let private_message_report_view = blocking(context.pool(), move |conn| {
-      PrivateMessageReportView::read(conn, report_id)
-    })
-    .await??;
+    if self.resolved {
+      PrivateMessageReport::resolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    } else {
+      PrivateMessageReport::unresolve(context.pool(), report_id, person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
+    }
+
+    let private_message_report_view =
+      PrivateMessageReportView::read(context.pool(), report_id).await?;
 
     let res = PrivateMessageReportResponse {
       private_message_report_view,
diff --git a/crates/api/src/site/leave_admin.rs b/crates/api/src/site/leave_admin.rs
index 9ba48f65..aee747be 100644
--- a/crates/api/src/site/leave_admin.rs
+++ b/crates/api/src/site/leave_admin.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{GetSiteResponse, LeaveAdmin},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::{
   source::{
@@ -35,20 +35,18 @@ impl Perform for LeaveAdmin {
     is_admin(&local_user_view)?;
 
     // Make sure there isn't just one admin (so if one leaves, there will still be one left)
-    let admins = blocking(context.pool(), PersonViewSafe::admins).await??;
+    let admins = PersonViewSafe::admins(context.pool()).await?;
     if admins.len() == 1 {
       return Err(LemmyError::from_message("cannot_leave_admin"));
     }
 
     let person_id = local_user_view.person.id;
-    blocking(context.pool(), move |conn| {
-      Person::update(
-        conn,
-        person_id,
-        &PersonUpdateForm::builder().admin(Some(false)).build(),
-      )
-    })
-    .await??;
+    Person::update(
+      context.pool(),
+      person_id,
+      &PersonUpdateForm::builder().admin(Some(false)).build(),
+    )
+    .await?;
 
     // Mod tables
     let form = ModAddForm {
@@ -57,14 +55,14 @@ impl Perform for LeaveAdmin {
       removed: Some(true),
     };
 
-    blocking(context.pool(), move |conn| ModAdd::create(conn, &form)).await??;
+    ModAdd::create(context.pool(), &form).await?;
 
     // Reread site and admins
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
-    let admins = blocking(context.pool(), PersonViewSafe::admins).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
+    let admins = PersonViewSafe::admins(context.pool()).await?;
 
-    let all_languages = blocking(context.pool(), Language::read_all).await??;
-    let discussion_languages = blocking(context.pool(), SiteLanguage::read_local).await??;
+    let all_languages = Language::read_all(context.pool()).await?;
+    let discussion_languages = SiteLanguage::read_local(context.pool()).await?;
 
     Ok(GetSiteResponse {
       site_view,
diff --git a/crates/api/src/site/mod_log.rs b/crates/api/src/site/mod_log.rs
index 6241c509..f1ab9f45 100644
--- a/crates/api/src/site/mod_log.rs
+++ b/crates/api/src/site/mod_log.rs
@@ -2,13 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{GetModlog, GetModlogResponse},
-  utils::{
-    blocking,
-    check_private_instance,
-    get_local_user_view_from_jwt_opt,
-    is_admin,
-    is_mod_or_admin,
-  },
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_admin, is_mod_or_admin},
 };
 use lemmy_db_schema::{
   newtypes::{CommunityId, PersonId},
@@ -52,7 +46,7 @@ impl Perform for GetModlog {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -88,81 +82,43 @@ impl Perform for GetModlog {
       hide_modlog_names,
     };
     let removed_posts = match type_ {
-      All | ModRemovePost => {
-        blocking(context.pool(), move |conn| {
-          ModRemovePostView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModRemovePost => ModRemovePostView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let locked_posts = match type_ {
-      All | ModLockPost => {
-        blocking(context.pool(), move |conn| {
-          ModLockPostView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModLockPost => ModLockPostView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let stickied_posts = match type_ {
-      All | ModStickyPost => {
-        blocking(context.pool(), move |conn| {
-          ModStickyPostView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModStickyPost => ModStickyPostView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let removed_comments = match type_ {
-      All | ModRemoveComment => {
-        blocking(context.pool(), move |conn| {
-          ModRemoveCommentView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModRemoveComment => ModRemoveCommentView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let banned_from_community = match type_ {
-      All | ModBanFromCommunity => {
-        blocking(context.pool(), move |conn| {
-          ModBanFromCommunityView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModBanFromCommunity => ModBanFromCommunityView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let added_to_community = match type_ {
-      All | ModAddCommunity => {
-        blocking(context.pool(), move |conn| {
-          ModAddCommunityView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModAddCommunity => ModAddCommunityView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let transferred_to_community = match type_ {
-      All | ModTransferCommunity => {
-        blocking(context.pool(), move |conn| {
-          ModTransferCommunityView::list(conn, params)
-        })
-        .await??
-      }
+      All | ModTransferCommunity => ModTransferCommunityView::list(context.pool(), params).await?,
       _ => Default::default(),
     };
 
     let hidden_communities = match type_ {
       All | ModHideCommunity if other_person_id.is_none() => {
-        blocking(context.pool(), move |conn| {
-          ModHideCommunityView::list(conn, params)
-        })
-        .await??
+        ModHideCommunityView::list(context.pool(), params).await?
       }
       _ => Default::default(),
     };
@@ -177,49 +133,46 @@ impl Perform for GetModlog {
       admin_purged_posts,
       admin_purged_comments,
     ) = if data.community_id.is_none() {
-      blocking(context.pool(), move |conn| {
-        Ok((
-          match type_ {
-            All | ModBan => ModBanView::list(conn, params)?,
-            _ => Default::default(),
-          },
-          match type_ {
-            All | ModAdd => ModAddView::list(conn, params)?,
-            _ => Default::default(),
-          },
-          match type_ {
-            All | ModRemoveCommunity if other_person_id.is_none() => {
-              ModRemoveCommunityView::list(conn, params)?
-            }
-            _ => Default::default(),
-          },
-          match type_ {
-            All | AdminPurgePerson if other_person_id.is_none() => {
-              AdminPurgePersonView::list(conn, params)?
-            }
-            _ => Default::default(),
-          },
-          match type_ {
-            All | AdminPurgeCommunity if other_person_id.is_none() => {
-              AdminPurgeCommunityView::list(conn, params)?
-            }
-            _ => Default::default(),
-          },
-          match type_ {
-            All | AdminPurgePost if other_person_id.is_none() => {
-              AdminPurgePostView::list(conn, params)?
-            }
-            _ => Default::default(),
-          },
-          match type_ {
-            All | AdminPurgeComment if other_person_id.is_none() => {
-              AdminPurgeCommentView::list(conn, params)?
-            }
-            _ => Default::default(),
-          },
-        )) as Result<_, LemmyError>
-      })
-      .await??
+      (
+        match type_ {
+          All | ModBan => ModBanView::list(context.pool(), params).await?,
+          _ => Default::default(),
+        },
+        match type_ {
+          All | ModAdd => ModAddView::list(context.pool(), params).await?,
+          _ => Default::default(),
+        },
+        match type_ {
+          All | ModRemoveCommunity if other_person_id.is_none() => {
+            ModRemoveCommunityView::list(context.pool(), params).await?
+          }
+          _ => Default::default(),
+        },
+        match type_ {
+          All | AdminPurgePerson if other_person_id.is_none() => {
+            AdminPurgePersonView::list(context.pool(), params).await?
+          }
+          _ => Default::default(),
+        },
+        match type_ {
+          All | AdminPurgeCommunity if other_person_id.is_none() => {
+            AdminPurgeCommunityView::list(context.pool(), params).await?
+          }
+          _ => Default::default(),
+        },
+        match type_ {
+          All | AdminPurgePost if other_person_id.is_none() => {
+            AdminPurgePostView::list(context.pool(), params).await?
+          }
+          _ => Default::default(),
+        },
+        match type_ {
+          All | AdminPurgeComment if other_person_id.is_none() => {
+            AdminPurgeCommentView::list(context.pool(), params).await?
+          }
+          _ => Default::default(),
+        },
+      )
     } else {
       Default::default()
     };
diff --git a/crates/api/src/site/purge/comment.rs b/crates/api/src/site/purge/comment.rs
index e8509318..fa4b508a 100644
--- a/crates/api/src/site/purge/comment.rs
+++ b/crates/api/src/site/purge/comment.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{PurgeComment, PurgeItemResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::{
   source::{
@@ -34,16 +34,13 @@ impl Perform for PurgeComment {
     let comment_id = data.comment_id;
 
     // Read the comment to get the post_id
-    let comment = blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??;
+    let comment = Comment::read(context.pool(), comment_id).await?;
 
     let post_id = comment.post_id;
 
     // TODO read comments for pictrs images and purge them
 
-    blocking(context.pool(), move |conn| {
-      Comment::delete(conn, comment_id)
-    })
-    .await??;
+    Comment::delete(context.pool(), comment_id).await?;
 
     // Mod tables
     let reason = data.reason.to_owned();
@@ -53,10 +50,7 @@ impl Perform for PurgeComment {
       post_id,
     };
 
-    blocking(context.pool(), move |conn| {
-      AdminPurgeComment::create(conn, &form)
-    })
-    .await??;
+    AdminPurgeComment::create(context.pool(), &form).await?;
 
     Ok(PurgeItemResponse { success: true })
   }
diff --git a/crates/api/src/site/purge/community.rs b/crates/api/src/site/purge/community.rs
index 5f1e3888..33781834 100644
--- a/crates/api/src/site/purge/community.rs
+++ b/crates/api/src/site/purge/community.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   request::purge_image_from_pictrs,
   site::{PurgeCommunity, PurgeItemResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin, purge_image_posts_for_community},
+  utils::{get_local_user_view_from_jwt, is_admin, purge_image_posts_for_community},
 };
 use lemmy_db_schema::{
   source::{
@@ -35,10 +35,7 @@ impl Perform for PurgeCommunity {
     let community_id = data.community_id;
 
     // Read the community to get its images
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
 
     if let Some(banner) = community.banner {
       purge_image_from_pictrs(context.client(), context.settings(), &banner)
@@ -60,10 +57,7 @@ impl Perform for PurgeCommunity {
     )
     .await?;
 
-    blocking(context.pool(), move |conn| {
-      Community::delete(conn, community_id)
-    })
-    .await??;
+    Community::delete(context.pool(), community_id).await?;
 
     // Mod tables
     let reason = data.reason.to_owned();
@@ -72,10 +66,7 @@ impl Perform for PurgeCommunity {
       reason,
     };
 
-    blocking(context.pool(), move |conn| {
-      AdminPurgeCommunity::create(conn, &form)
-    })
-    .await??;
+    AdminPurgeCommunity::create(context.pool(), &form).await?;
 
     Ok(PurgeItemResponse { success: true })
   }
diff --git a/crates/api/src/site/purge/person.rs b/crates/api/src/site/purge/person.rs
index 350b9a47..6ac30276 100644
--- a/crates/api/src/site/purge/person.rs
+++ b/crates/api/src/site/purge/person.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   request::purge_image_from_pictrs,
   site::{PurgeItemResponse, PurgePerson},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin, purge_image_posts_for_person},
+  utils::{get_local_user_view_from_jwt, is_admin, purge_image_posts_for_person},
 };
 use lemmy_db_schema::{
   source::{
@@ -34,7 +34,7 @@ impl Perform for PurgePerson {
 
     // Read the person to get their images
     let person_id = data.person_id;
-    let person = blocking(context.pool(), move |conn| Person::read(conn, person_id)).await??;
+    let person = Person::read(context.pool(), person_id).await?;
 
     if let Some(banner) = person.banner {
       purge_image_from_pictrs(context.client(), context.settings(), &banner)
@@ -56,7 +56,7 @@ impl Perform for PurgePerson {
     )
     .await?;
 
-    blocking(context.pool(), move |conn| Person::delete(conn, person_id)).await??;
+    Person::delete(context.pool(), person_id).await?;
 
     // Mod tables
     let reason = data.reason.to_owned();
@@ -65,10 +65,7 @@ impl Perform for PurgePerson {
       reason,
     };
 
-    blocking(context.pool(), move |conn| {
-      AdminPurgePerson::create(conn, &form)
-    })
-    .await??;
+    AdminPurgePerson::create(context.pool(), &form).await?;
 
     Ok(PurgeItemResponse { success: true })
   }
diff --git a/crates/api/src/site/purge/post.rs b/crates/api/src/site/purge/post.rs
index b7e13ade..ca10bb8c 100644
--- a/crates/api/src/site/purge/post.rs
+++ b/crates/api/src/site/purge/post.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   request::purge_image_from_pictrs,
   site::{PurgeItemResponse, PurgePost},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::{
   source::{
@@ -35,7 +35,7 @@ impl Perform for PurgePost {
     let post_id = data.post_id;
 
     // Read the post to get the community_id
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post = Post::read(context.pool(), post_id).await?;
 
     // Purge image
     if let Some(url) = post.url {
@@ -52,7 +52,7 @@ impl Perform for PurgePost {
 
     let community_id = post.community_id;
 
-    blocking(context.pool(), move |conn| Post::delete(conn, post_id)).await??;
+    Post::delete(context.pool(), post_id).await?;
 
     // Mod tables
     let reason = data.reason.to_owned();
@@ -62,10 +62,7 @@ impl Perform for PurgePost {
       community_id,
     };
 
-    blocking(context.pool(), move |conn| {
-      AdminPurgePost::create(conn, &form)
-    })
-    .await??;
+    AdminPurgePost::create(context.pool(), &form).await?;
 
     Ok(PurgeItemResponse { success: true })
   }
diff --git a/crates/api/src/site/registration_applications/approve.rs b/crates/api/src/site/registration_applications/approve.rs
index 129e92b7..bb125259 100644
--- a/crates/api/src/site/registration_applications/approve.rs
+++ b/crates/api/src/site/registration_applications/approve.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin, send_application_approved_email},
+  utils::{get_local_user_view_from_jwt, is_admin, send_application_approved_email},
 };
 use lemmy_db_schema::{
   source::{
@@ -41,10 +41,8 @@ impl Perform for ApproveRegistrationApplication {
       deny_reason,
     };
 
-    let registration_application = blocking(context.pool(), move |conn| {
-      RegistrationApplication::update(conn, app_id, &app_form)
-    })
-    .await??;
+    let registration_application =
+      RegistrationApplication::update(context.pool(), app_id, &app_form).await?;
 
     // Update the local_user row
     let local_user_form = LocalUserUpdateForm::builder()
@@ -52,16 +50,10 @@ impl Perform for ApproveRegistrationApplication {
       .build();
 
     let approved_user_id = registration_application.local_user_id;
-    blocking(context.pool(), move |conn| {
-      LocalUser::update(conn, approved_user_id, &local_user_form)
-    })
-    .await??;
+    LocalUser::update(context.pool(), approved_user_id, &local_user_form).await?;
 
     if data.approve {
-      let approved_local_user_view = blocking(context.pool(), move |conn| {
-        LocalUserView::read(conn, approved_user_id)
-      })
-      .await??;
+      let approved_local_user_view = LocalUserView::read(context.pool(), approved_user_id).await?;
 
       if approved_local_user_view.local_user.email.is_some() {
         send_application_approved_email(&approved_local_user_view, context.settings())?;
@@ -69,10 +61,8 @@ impl Perform for ApproveRegistrationApplication {
     }
 
     // Read the view
-    let registration_application = blocking(context.pool(), move |conn| {
-      RegistrationApplicationView::read(conn, app_id)
-    })
-    .await??;
+    let registration_application =
+      RegistrationApplicationView::read(context.pool(), app_id).await?;
 
     Ok(Self::Response {
       registration_application,
diff --git a/crates/api/src/site/registration_applications/list.rs b/crates/api/src/site/registration_applications/list.rs
index 9329151b..3d9ed326 100644
--- a/crates/api/src/site/registration_applications/list.rs
+++ b/crates/api/src/site/registration_applications/list.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_db_views::registration_application_view::RegistrationApplicationQuery;
@@ -22,7 +22,7 @@ impl Perform for ListRegistrationApplications {
     let data = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Make sure user is an admin
     is_admin(&local_user_view)?;
@@ -32,17 +32,15 @@ impl Perform for ListRegistrationApplications {
 
     let page = data.page;
     let limit = data.limit;
-    let registration_applications = blocking(context.pool(), move |conn| {
-      RegistrationApplicationQuery::builder()
-        .conn(conn)
-        .unread_only(unread_only)
-        .verified_email_only(Some(verified_email_only))
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let registration_applications = RegistrationApplicationQuery::builder()
+      .pool(context.pool())
+      .unread_only(unread_only)
+      .verified_email_only(Some(verified_email_only))
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     let res = Self::Response {
       registration_applications,
diff --git a/crates/api/src/site/registration_applications/unread_count.rs b/crates/api/src/site/registration_applications/unread_count.rs
index 32db67bb..7fb8906a 100644
--- a/crates/api/src/site/registration_applications/unread_count.rs
+++ b/crates/api/src/site/registration_applications/unread_count.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_db_views::structs::RegistrationApplicationView;
@@ -21,17 +21,15 @@ impl Perform for GetUnreadRegistrationApplicationCount {
     let data = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Only let admins do this
     is_admin(&local_user_view)?;
 
     let verified_email_only = local_site.require_email_verification;
 
-    let registration_applications = blocking(context.pool(), move |conn| {
-      RegistrationApplicationView::get_unread_count(conn, verified_email_only)
-    })
-    .await??;
+    let registration_applications =
+      RegistrationApplicationView::get_unread_count(context.pool(), verified_email_only).await?;
 
     Ok(Self::Response {
       registration_applications,
diff --git a/crates/api/src/site/resolve_object.rs b/crates/api/src/site/resolve_object.rs
index 5d322eec..816522c7 100644
--- a/crates/api/src/site/resolve_object.rs
+++ b/crates/api/src/site/resolve_object.rs
@@ -3,7 +3,7 @@ use actix_web::web::Data;
 use diesel::NotFound;
 use lemmy_api_common::{
   site::{ResolveObject, ResolveObjectResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_apub::fetcher::search::{search_query_to_object_id, SearchableObjects};
 use lemmy_db_schema::{newtypes::PersonId, source::local_site::LocalSite, utils::DbPool};
@@ -25,7 +25,7 @@ impl Perform for ResolveObject {
     let local_user_view =
       get_local_user_view_from_jwt_opt(self.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
     check_private_instance(&local_user_view, &local_site)?;
 
     let res = search_query_to_object_id(&self.q, local_user_view.is_none(), context)
@@ -53,20 +53,19 @@ async fn convert_response(
   match object {
     Person(p) => {
       removed_or_deleted = p.deleted;
-      res.person = Some(blocking(pool, move |conn| PersonViewSafe::read(conn, p.id)).await??)
+      res.person = Some(PersonViewSafe::read(pool, p.id).await?)
     }
     Community(c) => {
       removed_or_deleted = c.deleted || c.removed;
-      res.community =
-        Some(blocking(pool, move |conn| CommunityView::read(conn, c.id, user_id)).await??)
+      res.community = Some(CommunityView::read(pool, c.id, user_id).await?)
     }
     Post(p) => {
       removed_or_deleted = p.deleted || p.removed;
-      res.post = Some(blocking(pool, move |conn| PostView::read(conn, p.id, user_id)).await??)
+      res.post = Some(PostView::read(pool, p.id, user_id).await?)
     }
     Comment(c) => {
       removed_or_deleted = c.deleted || c.removed;
-      res.comment = Some(blocking(pool, move |conn| CommentView::read(conn, c.id, user_id)).await??)
+      res.comment = Some(CommentView::read(pool, c.id, user_id).await?)
     }
   };
   // if the object was deleted from database, dont return it
diff --git a/crates/api/src/site/search.rs b/crates/api/src/site/search.rs
index 6c02f9ac..970cb500 100644
--- a/crates/api/src/site/search.rs
+++ b/crates/api/src/site/search.rs
@@ -2,7 +2,7 @@ use crate::Perform;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{Search, SearchResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::community::ApubCommunity};
 use lemmy_db_schema::{
@@ -31,7 +31,7 @@ impl Perform for Search {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -63,68 +63,60 @@ impl Perform for Search {
     let creator_id = data.creator_id;
     match search_type {
       SearchType::Posts => {
-        posts = blocking(context.pool(), move |conn| {
-          PostQuery::builder()
-            .conn(conn)
-            .sort(sort)
-            .listing_type(listing_type)
-            .community_id(community_id)
-            .community_actor_id(community_actor_id)
-            .creator_id(creator_id)
-            .local_user(local_user.as_ref())
-            .search_term(Some(q))
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        posts = PostQuery::builder()
+          .pool(context.pool())
+          .sort(sort)
+          .listing_type(listing_type)
+          .community_id(community_id)
+          .community_actor_id(community_actor_id)
+          .creator_id(creator_id)
+          .local_user(local_user.as_ref())
+          .search_term(Some(q))
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
       }
       SearchType::Comments => {
-        comments = blocking(context.pool(), move |conn| {
-          CommentQuery::builder()
-            .conn(conn)
-            .sort(sort.map(post_to_comment_sort_type))
-            .listing_type(listing_type)
-            .search_term(Some(q))
-            .community_id(community_id)
-            .community_actor_id(community_actor_id)
-            .creator_id(creator_id)
-            .local_user(local_user.as_ref())
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        comments = CommentQuery::builder()
+          .pool(context.pool())
+          .sort(sort.map(post_to_comment_sort_type))
+          .listing_type(listing_type)
+          .search_term(Some(q))
+          .community_id(community_id)
+          .community_actor_id(community_actor_id)
+          .creator_id(creator_id)
+          .local_user(local_user.as_ref())
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
       }
       SearchType::Communities => {
-        communities = blocking(context.pool(), move |conn| {
-          CommunityQuery::builder()
-            .conn(conn)
-            .sort(sort)
-            .listing_type(listing_type)
-            .search_term(Some(q))
-            .local_user(local_user.as_ref())
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        communities = CommunityQuery::builder()
+          .pool(context.pool())
+          .sort(sort)
+          .listing_type(listing_type)
+          .search_term(Some(q))
+          .local_user(local_user.as_ref())
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
       }
       SearchType::Users => {
-        users = blocking(context.pool(), move |conn| {
-          PersonQuery::builder()
-            .conn(conn)
-            .sort(sort)
-            .search_term(Some(q))
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        users = PersonQuery::builder()
+          .pool(context.pool())
+          .sort(sort)
+          .search_term(Some(q))
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
       }
       SearchType::All => {
         // If the community or creator is included, dont search communities or users
@@ -133,62 +125,56 @@ impl Perform for Search {
         let community_actor_id_2 = community_actor_id.to_owned();
 
         let local_user_ = local_user.clone();
-        posts = blocking(context.pool(), move |conn| {
-          PostQuery::builder()
-            .conn(conn)
-            .sort(sort)
-            .listing_type(listing_type)
-            .community_id(community_id)
-            .community_actor_id(community_actor_id_2)
-            .creator_id(creator_id)
-            .local_user(local_user_.as_ref())
-            .search_term(Some(q))
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        posts = PostQuery::builder()
+          .pool(context.pool())
+          .sort(sort)
+          .listing_type(listing_type)
+          .community_id(community_id)
+          .community_actor_id(community_actor_id_2)
+          .creator_id(creator_id)
+          .local_user(local_user_.as_ref())
+          .search_term(Some(q))
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
 
         let q = data.q.to_owned();
         let community_actor_id = community_actor_id.to_owned();
 
         let local_user_ = local_user.clone();
-        comments = blocking(context.pool(), move |conn| {
-          CommentQuery::builder()
-            .conn(conn)
-            .sort(sort.map(post_to_comment_sort_type))
-            .listing_type(listing_type)
-            .search_term(Some(q))
-            .community_id(community_id)
-            .community_actor_id(community_actor_id)
-            .creator_id(creator_id)
-            .local_user(local_user_.as_ref())
-            .page(page)
-            .limit(limit)
-            .build()
-            .list()
-        })
-        .await??;
+        comments = CommentQuery::builder()
+          .pool(context.pool())
+          .sort(sort.map(post_to_comment_sort_type))
+          .listing_type(listing_type)
+          .search_term(Some(q))
+          .community_id(community_id)
+          .community_actor_id(community_actor_id)
+          .creator_id(creator_id)
+          .local_user(local_user_.as_ref())
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
 
         let q = data.q.to_owned();
 
         communities = if community_or_creator_included {
           vec![]
         } else {
-          blocking(context.pool(), move |conn| {
-            CommunityQuery::builder()
-              .conn(conn)
-              .sort(sort)
-              .listing_type(listing_type)
-              .search_term(Some(q))
-              .local_user(local_user.as_ref())
-              .page(page)
-              .limit(limit)
-              .build()
-              .list()
-          })
-          .await??
+          CommunityQuery::builder()
+            .pool(context.pool())
+            .sort(sort)
+            .listing_type(listing_type)
+            .search_term(Some(q))
+            .local_user(local_user.as_ref())
+            .page(page)
+            .limit(limit)
+            .build()
+            .list()
+            .await?
         };
 
         let q = data.q.to_owned();
@@ -196,35 +182,31 @@ impl Perform for Search {
         users = if community_or_creator_included {
           vec![]
         } else {
-          blocking(context.pool(), move |conn| {
-            PersonQuery::builder()
-              .conn(conn)
-              .sort(sort)
-              .search_term(Some(q))
-              .page(page)
-              .limit(limit)
-              .build()
-              .list()
-          })
-          .await??
-        };
-      }
-      SearchType::Url => {
-        posts = blocking(context.pool(), move |conn| {
-          PostQuery::builder()
-            .conn(conn)
+          PersonQuery::builder()
+            .pool(context.pool())
             .sort(sort)
-            .listing_type(listing_type)
-            .community_id(community_id)
-            .community_actor_id(community_actor_id)
-            .creator_id(creator_id)
-            .url_search(Some(q))
+            .search_term(Some(q))
             .page(page)
             .limit(limit)
             .build()
             .list()
-        })
-        .await??;
+            .await?
+        };
+      }
+      SearchType::Url => {
+        posts = PostQuery::builder()
+          .pool(context.pool())
+          .sort(sort)
+          .listing_type(listing_type)
+          .community_id(community_id)
+          .community_actor_id(community_actor_id)
+          .creator_id(creator_id)
+          .url_search(Some(q))
+          .page(page)
+          .limit(limit)
+          .build()
+          .list()
+          .await?;
       }
     };
 
diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml
index 406517cd..7bd38b6a 100644
--- a/crates/api_common/Cargo.toml
+++ b/crates/api_common/Cargo.toml
@@ -24,11 +24,11 @@ lemmy_db_views_moderator = { version = "=0.16.5", path = "../db_views_moderator"
 lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor" }
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema", default-features = false }
 lemmy_utils = { version = "=0.16.5", path = "../utils", optional = true }
-serde = { version = "1.0.145", features = ["derive"] }
+serde = { version = "1.0.147", features = ["derive"] }
 url = "2.3.1"
 actix-web = { version = "4.2.1", default-features = false, features = ["cookies"], optional = true }
 chrono = { version = "0.4.22", features = ["serde"], optional = true }
-diesel = { version = "2.0.0", optional = true }
+diesel = { version = "2.0.2", optional = true }
 tracing = { version = "0.1.36", optional = true }
 rosetta-i18n = { version = "0.1.2", optional = true }
 percent-encoding = { version = "2.2.0", optional = true }
diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs
index 88e1c3ac..e4619e64 100644
--- a/crates/api_common/src/site.rs
+++ b/crates/api_common/src/site.rs
@@ -125,10 +125,10 @@ pub struct CreateSite {
   pub private_instance: Option<bool>,
   pub default_theme: Option<String>,
   pub default_post_listing_type: Option<String>,
+  pub legal_information: Option<String>,
   pub application_email_admins: Option<bool>,
-  pub auth: Sensitive<String>,
   pub hide_modlog_mod_names: Option<bool>,
-  pub legal_information: Option<String>,
+  pub discussion_languages: Option<Vec<LanguageId>>,
   pub slur_filter_regex: Option<String>,
   pub actor_name_max_length: Option<i32>,
   pub rate_limit_message: Option<i32>,
@@ -152,6 +152,7 @@ pub struct CreateSite {
   pub captcha_difficulty: Option<String>,
   pub allowed_instances: Option<Vec<String>>,
   pub blocked_instances: Option<Vec<String>>,
+  pub auth: Sensitive<String>,
 }
 
 #[derive(Debug, Serialize, Deserialize, Clone, Default)]
diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs
index 8c341c44..a65845cc 100644
--- a/crates/api_common/src/utils.rs
+++ b/crates/api_common/src/utils.rs
@@ -44,33 +44,13 @@ use rosetta_i18n::{Language, LanguageId};
 use std::str::FromStr;
 use tracing::warn;
 
-pub async fn blocking<F, T>(pool: &DbPool, f: F) -> Result<T, LemmyError>
-where
-  F: FnOnce(&mut diesel::PgConnection) -> T + Send + 'static,
-  T: Send + 'static,
-{
-  let pool = pool.clone();
-  let blocking_span = tracing::info_span!("blocking operation");
-  actix_web::web::block(move || {
-    let entered = blocking_span.enter();
-    let mut conn = pool.get()?;
-    let res = (f)(&mut conn);
-    drop(entered);
-    Ok(res) as Result<T, LemmyError>
-  })
-  .await?
-}
-
 #[tracing::instrument(skip_all)]
 pub async fn is_mod_or_admin(
   pool: &DbPool,
   person_id: PersonId,
   community_id: CommunityId,
 ) -> Result<(), LemmyError> {
-  let is_mod_or_admin = blocking(pool, move |conn| {
-    CommunityView::is_mod_or_admin(conn, person_id, community_id)
-  })
-  .await?;
+  let is_mod_or_admin = CommunityView::is_mod_or_admin(pool, person_id, community_id).await?;
   if !is_mod_or_admin {
     return Err(LemmyError::from_message("not_a_mod_or_admin"));
   }
@@ -86,8 +66,8 @@ pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
 
 #[tracing::instrument(skip_all)]
 pub async fn get_post(post_id: PostId, pool: &DbPool) -> Result<Post, LemmyError> {
-  blocking(pool, move |conn| Post::read(conn, post_id))
-    .await?
+  Post::read(pool, post_id)
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))
 }
 
@@ -99,11 +79,9 @@ pub async fn mark_post_as_read(
 ) -> Result<PostRead, LemmyError> {
   let post_read_form = PostReadForm { post_id, person_id };
 
-  blocking(pool, move |conn| {
-    PostRead::mark_as_read(conn, &post_read_form)
-  })
-  .await?
-  .map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
+  PostRead::mark_as_read(pool, &post_read_form)
+    .await
+    .map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
 }
 
 #[tracing::instrument(skip_all)]
@@ -114,11 +92,9 @@ pub async fn mark_post_as_unread(
 ) -> Result<usize, LemmyError> {
   let post_read_form = PostReadForm { post_id, person_id };
 
-  blocking(pool, move |conn| {
-    PostRead::mark_as_unread(conn, &post_read_form)
-  })
-  .await?
-  .map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
+  PostRead::mark_as_unread(pool, &post_read_form)
+    .await
+    .map_err(|e| LemmyError::from_error_message(e, "couldnt_mark_post_as_read"))
 }
 
 #[tracing::instrument(skip_all)]
@@ -131,8 +107,7 @@ pub async fn get_local_user_view_from_jwt(
     .map_err(|e| e.with_message("not_logged_in"))?
     .claims;
   let local_user_id = LocalUserId(claims.sub);
-  let local_user_view =
-    blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
+  let local_user_view = LocalUserView::read(pool, local_user_id).await?;
   check_user_valid(
     local_user_view.person.banned,
     local_user_view.person.ban_expires,
@@ -181,10 +156,7 @@ pub async fn get_local_user_settings_view_from_jwt_opt(
         .map_err(|e| e.with_message("not_logged_in"))?
         .claims;
       let local_user_id = LocalUserId(claims.sub);
-      let local_user_view = blocking(pool, move |conn| {
-        LocalUserSettingsView::read(conn, local_user_id)
-      })
-      .await??;
+      let local_user_view = LocalUserSettingsView::read(pool, local_user_id).await?;
       check_user_valid(
         local_user_view.person.banned,
         local_user_view.person.ban_expires,
@@ -222,9 +194,10 @@ pub async fn check_community_ban(
   community_id: CommunityId,
   pool: &DbPool,
 ) -> Result<(), LemmyError> {
-  let is_banned =
-    move |conn: &mut _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
-  if blocking(pool, is_banned).await? {
+  let is_banned = CommunityPersonBanView::get(pool, person_id, community_id)
+    .await
+    .is_ok();
+  if is_banned {
     Err(LemmyError::from_message("community_ban"))
   } else {
     Ok(())
@@ -236,8 +209,8 @@ pub async fn check_community_deleted_or_removed(
   community_id: CommunityId,
   pool: &DbPool,
 ) -> Result<(), LemmyError> {
-  let community = blocking(pool, move |conn| Community::read(conn, community_id))
-    .await?
+  let community = Community::read(pool, community_id)
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
   if community.deleted || community.removed {
     Err(LemmyError::from_message("deleted"))
@@ -260,8 +233,10 @@ pub async fn check_person_block(
   potential_blocker_id: PersonId,
   pool: &DbPool,
 ) -> Result<(), LemmyError> {
-  let is_blocked = move |conn: &mut _| PersonBlock::read(conn, potential_blocker_id, my_id).is_ok();
-  if blocking(pool, is_blocked).await? {
+  let is_blocked = PersonBlock::read(pool, potential_blocker_id, my_id)
+    .await
+    .is_ok();
+  if is_blocked {
     Err(LemmyError::from_message("person_block"))
   } else {
     Ok(())
@@ -294,9 +269,9 @@ pub async fn build_federated_instances(
 ) -> Result<Option<FederatedInstances>, LemmyError> {
   if local_site.federation_enabled {
     // TODO I hate that this requires 3 queries
-    let linked = blocking(pool, Instance::linked).await??;
-    let allowed = blocking(pool, Instance::allowlist).await??;
-    let blocked = blocking(pool, Instance::blocklist).await??;
+    let linked = Instance::linked(pool).await?;
+    let allowed = Instance::allowlist(pool).await?;
+    let blocked = Instance::blocklist(pool).await?;
 
     // These can return empty vectors, so convert them to options
     let allowed = (!allowed.is_empty()).then(|| allowed);
@@ -374,10 +349,7 @@ pub async fn send_password_reset_email(
   // Insert the row
   let token2 = token.clone();
   let local_user_id = user.local_user.id;
-  blocking(pool, move |conn| {
-    PasswordResetRequest::create_token(conn, local_user_id, &token2)
-  })
-  .await??;
+  PasswordResetRequest::create_token(pool, local_user_id, &token2).await?;
 
   let email = &user.local_user.email.to_owned().expect("email");
   let lang = get_interface_language(user);
@@ -405,7 +377,7 @@ pub async fn send_verification_email(
     settings.get_protocol_and_hostname(),
     &form.verification_token
   );
-  blocking(pool, move |conn| EmailVerification::create(conn, &form)).await??;
+  EmailVerification::create(pool, &form).await?;
 
   let lang = get_interface_language(user);
   let subject = lang.verify_email_subject(&settings.hostname);
@@ -491,10 +463,7 @@ pub async fn send_new_applicant_email_to_admins(
   settings: &Settings,
 ) -> Result<(), LemmyError> {
   // Collect the admins with emails
-  let admins = blocking(pool, move |conn| {
-    LocalUserSettingsView::list_admins_with_emails(conn)
-  })
-  .await??;
+  let admins = LocalUserSettingsView::list_admins_with_emails(pool).await?;
 
   let applications_link = &format!(
     "{}/registration_applications",
@@ -522,10 +491,7 @@ pub async fn check_registration_application(
   {
     // Fetch the registration, see if its denied
     let local_user_id = local_user_view.local_user.id;
-    let registration = blocking(pool, move |conn| {
-      RegistrationApplication::find_by_local_user_id(conn, local_user_id)
-    })
-    .await??;
+    let registration = RegistrationApplication::find_by_local_user_id(pool, local_user_id).await?;
     if let Some(deny_reason) = registration.deny_reason {
       let lang = get_interface_language(local_user_view);
       let registration_denied_message = format!("{}: {}", lang.registration_denied(), &deny_reason);
@@ -554,10 +520,7 @@ pub async fn purge_image_posts_for_person(
   settings: &Settings,
   client: &ClientWithMiddleware,
 ) -> Result<(), LemmyError> {
-  let posts = blocking(pool, move |conn: &mut _| {
-    Post::fetch_pictrs_posts_for_creator(conn, banned_person_id)
-  })
-  .await??;
+  let posts = Post::fetch_pictrs_posts_for_creator(pool, banned_person_id).await?;
   for post in posts {
     if let Some(url) = post.url {
       purge_image_from_pictrs(client, settings, &url).await.ok();
@@ -569,10 +532,7 @@ pub async fn purge_image_posts_for_person(
     }
   }
 
-  blocking(pool, move |conn| {
-    Post::remove_pictrs_post_images_and_thumbnails_for_creator(conn, banned_person_id)
-  })
-  .await??;
+  Post::remove_pictrs_post_images_and_thumbnails_for_creator(pool, banned_person_id).await?;
 
   Ok(())
 }
@@ -583,10 +543,7 @@ pub async fn purge_image_posts_for_community(
   settings: &Settings,
   client: &ClientWithMiddleware,
 ) -> Result<(), LemmyError> {
-  let posts = blocking(pool, move |conn: &mut _| {
-    Post::fetch_pictrs_posts_for_community(conn, banned_community_id)
-  })
-  .await??;
+  let posts = Post::fetch_pictrs_posts_for_community(pool, banned_community_id).await?;
   for post in posts {
     if let Some(url) = post.url {
       purge_image_from_pictrs(client, settings, &url).await.ok();
@@ -598,10 +555,7 @@ pub async fn purge_image_posts_for_community(
     }
   }
 
-  blocking(pool, move |conn| {
-    Post::remove_pictrs_post_images_and_thumbnails_for_community(conn, banned_community_id)
-  })
-  .await??;
+  Post::remove_pictrs_post_images_and_thumbnails_for_community(pool, banned_community_id).await?;
 
   Ok(())
 }
@@ -613,7 +567,7 @@ pub async fn remove_user_data(
   client: &ClientWithMiddleware,
 ) -> Result<(), LemmyError> {
   // Purge user images
-  let person = blocking(pool, move |conn| Person::read(conn, banned_person_id)).await??;
+  let person = Person::read(pool, banned_person_id).await?;
   if let Some(avatar) = person.avatar {
     purge_image_from_pictrs(client, settings, &avatar)
       .await
@@ -626,23 +580,18 @@ pub async fn remove_user_data(
   }
 
   // Update the fields to None
-  blocking(pool, move |conn| {
-    Person::update(
-      conn,
-      banned_person_id,
-      &PersonUpdateForm::builder()
-        .avatar(Some(None))
-        .banner(Some(None))
-        .build(),
-    )
-  })
-  .await??;
+  Person::update(
+    pool,
+    banned_person_id,
+    &PersonUpdateForm::builder()
+      .avatar(Some(None))
+      .banner(Some(None))
+      .build(),
+  )
+  .await?;
 
   // Posts
-  blocking(pool, move |conn: &mut _| {
-    Post::update_removed_for_creator(conn, banned_person_id, None, true)
-  })
-  .await??;
+  Post::update_removed_for_creator(pool, banned_person_id, None, true).await?;
 
   // Purge image posts
   purge_image_posts_for_person(banned_person_id, pool, settings, client).await?;
@@ -650,10 +599,7 @@ pub async fn remove_user_data(
   // Communities
   // Remove all communities where they're the top mod
   // for now, remove the communities manually
-  let first_mod_communities = blocking(pool, move |conn: &mut _| {
-    CommunityModeratorView::get_community_first_mods(conn)
-  })
-  .await??;
+  let first_mod_communities = CommunityModeratorView::get_community_first_mods(pool).await?;
 
   // Filter to only this banned users top communities
   let banned_user_first_communities: Vec<CommunityModeratorView> = first_mod_communities
@@ -663,14 +609,12 @@ pub async fn remove_user_data(
 
   for first_mod_community in banned_user_first_communities {
     let community_id = first_mod_community.community.id;
-    blocking(pool, move |conn| {
-      Community::update(
-        conn,
-        community_id,
-        &CommunityUpdateForm::builder().removed(Some(true)).build(),
-      )
-    })
-    .await??;
+    Community::update(
+      pool,
+      community_id,
+      &CommunityUpdateForm::builder().removed(Some(true)).build(),
+    )
+    .await?;
 
     // Delete the community images
     if let Some(icon) = first_mod_community.community.icon {
@@ -682,24 +626,19 @@ pub async fn remove_user_data(
         .ok();
     }
     // Update the fields to None
-    blocking(pool, move |conn| {
-      Community::update(
-        conn,
-        community_id,
-        &CommunityUpdateForm::builder()
-          .icon(Some(None))
-          .banner(Some(None))
-          .build(),
-      )
-    })
-    .await??;
+    Community::update(
+      pool,
+      community_id,
+      &CommunityUpdateForm::builder()
+        .icon(Some(None))
+        .banner(Some(None))
+        .build(),
+    )
+    .await?;
   }
 
   // Comments
-  blocking(pool, move |conn: &mut _| {
-    Comment::update_removed_for_creator(conn, banned_person_id, true)
-  })
-  .await??;
+  Comment::update_removed_for_creator(pool, banned_person_id, true).await?;
 
   Ok(())
 }
@@ -710,34 +649,27 @@ pub async fn remove_user_data_in_community(
   pool: &DbPool,
 ) -> Result<(), LemmyError> {
   // Posts
-  blocking(pool, move |conn| {
-    Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
-  })
-  .await??;
+  Post::update_removed_for_creator(pool, banned_person_id, Some(community_id), true).await?;
 
   // Comments
   // TODO Diesel doesn't allow updates with joins, so this has to be a loop
-  let comments = blocking(pool, move |conn| {
-    CommentQuery::builder()
-      .conn(conn)
-      .creator_id(Some(banned_person_id))
-      .community_id(Some(community_id))
-      .limit(Some(i64::MAX))
-      .build()
-      .list()
-  })
-  .await??;
+  let comments = CommentQuery::builder()
+    .pool(pool)
+    .creator_id(Some(banned_person_id))
+    .community_id(Some(community_id))
+    .limit(Some(i64::MAX))
+    .build()
+    .list()
+    .await?;
 
   for comment_view in &comments {
     let comment_id = comment_view.comment.id;
-    blocking(pool, move |conn| {
-      Comment::update(
-        conn,
-        comment_id,
-        &CommentUpdateForm::builder().removed(Some(true)).build(),
-      )
-    })
-    .await??;
+    Comment::update(
+      pool,
+      comment_id,
+      &CommentUpdateForm::builder().removed(Some(true)).build(),
+    )
+    .await?;
   }
 
   Ok(())
@@ -750,7 +682,7 @@ pub async fn delete_user_account(
   client: &ClientWithMiddleware,
 ) -> Result<(), LemmyError> {
   // Delete their images
-  let person = blocking(pool, move |conn| Person::read(conn, person_id)).await??;
+  let person = Person::read(pool, person_id).await?;
   if let Some(avatar) = person.avatar {
     purge_image_from_pictrs(client, settings, &avatar)
       .await
@@ -764,21 +696,19 @@ pub async fn delete_user_account(
   // No need to update avatar and banner, those are handled in Person::delete_account
 
   // Comments
-  let permadelete = move |conn: &mut _| Comment::permadelete_for_creator(conn, person_id);
-  blocking(pool, permadelete)
-    .await?
+  Comment::permadelete_for_creator(pool, person_id)
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
   // Posts
-  let permadelete = move |conn: &mut _| Post::permadelete_for_creator(conn, person_id);
-  blocking(pool, permadelete)
-    .await?
+  Post::permadelete_for_creator(pool, person_id)
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_post"))?;
 
   // Purge image posts
   purge_image_posts_for_person(person_id, pool, settings, client).await?;
 
-  blocking(pool, move |conn| Person::delete_account(conn, person_id)).await??;
+  Person::delete_account(pool, person_id).await?;
 
   Ok(())
 }
diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml
index 6608f22c..aa1ec1a0 100644
--- a/crates/api_crud/Cargo.toml
+++ b/crates/api_crud/Cargo.toml
@@ -18,10 +18,10 @@ lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["f
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
 activitypub_federation = "0.2.3"
 bcrypt = "0.13.0"
-serde_json = { version = "1.0.85", features = ["preserve_order"] }
-serde = { version = "1.0.145", features = ["derive"] }
+serde_json = { version = "1.0.87", features = ["preserve_order"] }
+serde = { version = "1.0.147", features = ["derive"] }
 actix-web = { version = "4.2.1", default-features = false }
 tracing = "0.1.36"
 url = { version = "2.3.1", features = ["serde"] }
-async-trait = "0.1.57"
+async-trait = "0.1.58"
 webmention = "0.4.0"
diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs
index ef13e54d..ff91baf2 100644
--- a/crates/api_crud/src/comment/create.rs
+++ b/crates/api_crud/src/comment/create.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, CreateComment},
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     check_post_deleted_or_removed,
@@ -52,7 +51,7 @@ impl PerformCrud for CreateComment {
     let data: &CreateComment = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let content_slurs_removed = remove_slurs(
       &data.content.to_owned(),
@@ -75,9 +74,7 @@ impl PerformCrud for CreateComment {
 
     // Fetch the parent, if it exists
     let parent_opt = if let Some(parent_id) = data.parent_id {
-      blocking(context.pool(), move |conn| Comment::read(conn, parent_id))
-        .await?
-        .ok()
+      Comment::read(context.pool(), parent_id).await.ok()
     } else {
       None
     };
@@ -97,10 +94,12 @@ impl PerformCrud for CreateComment {
       .unwrap_or(post.language_id);
     let language_id = data.language_id.unwrap_or(parent_language);
 
-    blocking(context.pool(), move |conn| {
-      CommunityLanguage::is_allowed_community_language(conn, Some(language_id), community_id)
-    })
-    .await??;
+    CommunityLanguage::is_allowed_community_language(
+      context.pool(),
+      Some(language_id),
+      community_id,
+    )
+    .await?;
 
     let comment_form = CommentInsertForm::builder()
       .content(content_slurs_removed.to_owned())
@@ -112,31 +111,26 @@ impl PerformCrud for CreateComment {
     // Create the comment
     let comment_form2 = comment_form.clone();
     let parent_path = parent_opt.to_owned().map(|t| t.path);
-    let inserted_comment = blocking(context.pool(), move |conn| {
-      Comment::create(conn, &comment_form2, parent_path.as_ref())
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_comment"))?;
+    let inserted_comment = Comment::create(context.pool(), &comment_form2, parent_path.as_ref())
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_comment"))?;
 
     // Necessary to update the ap_id
     let inserted_comment_id = inserted_comment.id;
     let protocol_and_hostname = context.settings().get_protocol_and_hostname();
 
-    let updated_comment: Comment =
-      blocking(context.pool(), move |conn| -> Result<Comment, LemmyError> {
-        let apub_id = generate_local_apub_endpoint(
-          EndpointType::Comment,
-          &inserted_comment_id.to_string(),
-          &protocol_and_hostname,
-        )?;
-        Ok(Comment::update(
-          conn,
-          inserted_comment_id,
-          &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(),
-        )?)
-      })
-      .await?
-      .map_err(|e| e.with_message("couldnt_create_comment"))?;
+    let apub_id = generate_local_apub_endpoint(
+      EndpointType::Comment,
+      &inserted_comment_id.to_string(),
+      &protocol_and_hostname,
+    )?;
+    let updated_comment = Comment::update(
+      context.pool(),
+      inserted_comment_id,
+      &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(),
+    )
+    .await
+    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_comment"))?;
 
     // Scan the comment for user mentions, add those rows
     let post_id = post.id;
@@ -159,9 +153,8 @@ impl PerformCrud for CreateComment {
       score: 1,
     };
 
-    let like = move |conn: &mut _| CommentLike::like(conn, &like_form);
-    blocking(context.pool(), like)
-      .await?
+    CommentLike::like(context.pool(), &like_form)
+      .await
       .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
 
     let apub_comment: ApubComment = updated_comment.into();
@@ -177,33 +170,28 @@ impl PerformCrud for CreateComment {
     // If its a reply, mark the parent as read
     if let Some(parent) = parent_opt {
       let parent_id = parent.id;
-      let comment_reply = blocking(context.pool(), move |conn| {
-        CommentReply::read_by_comment(conn, parent_id)
-      })
-      .await?;
+      let comment_reply = CommentReply::read_by_comment(context.pool(), parent_id).await;
       if let Ok(reply) = comment_reply {
-        blocking(context.pool(), move |conn| {
-          CommentReply::update(conn, reply.id, &CommentReplyUpdateForm { read: Some(true) })
-        })
-        .await?
+        CommentReply::update(
+          context.pool(),
+          reply.id,
+          &CommentReplyUpdateForm { read: Some(true) },
+        )
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_replies"))?;
       }
 
       // If the parent has PersonMentions mark them as read too
       let person_id = local_user_view.person.id;
-      let person_mention = blocking(context.pool(), move |conn| {
-        PersonMention::read_by_comment_and_person(conn, parent_id, person_id)
-      })
-      .await?;
+      let person_mention =
+        PersonMention::read_by_comment_and_person(context.pool(), parent_id, person_id).await;
       if let Ok(mention) = person_mention {
-        blocking(context.pool(), move |conn| {
-          PersonMention::update(
-            conn,
-            mention.id,
-            &PersonMentionUpdateForm { read: Some(true) },
-          )
-        })
-        .await?
+        PersonMention::update(
+          context.pool(),
+          mention.id,
+          &PersonMentionUpdateForm { read: Some(true) },
+        )
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_person_mentions"))?;
       }
     }
diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs
index 407d11cc..549d2f36 100644
--- a/crates/api_crud/src/comment/delete.rs
+++ b/crates/api_crud/src/comment/delete.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, DeleteComment},
-  utils::{blocking, check_community_ban, get_local_user_view_from_jwt},
+  utils::{check_community_ban, get_local_user_view_from_jwt},
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -36,10 +36,7 @@ impl PerformCrud for DeleteComment {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let comment_id = data.comment_id;
-    let orig_comment = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, None)
-    })
-    .await??;
+    let orig_comment = CommentView::read(context.pool(), comment_id, None).await?;
 
     // Dont delete it if its already been deleted.
     if orig_comment.comment.deleted == data.deleted {
@@ -60,18 +57,16 @@ impl PerformCrud for DeleteComment {
 
     // Do the delete
     let deleted = data.deleted;
-    let updated_comment = blocking(context.pool(), move |conn| {
-      Comment::update(
-        conn,
-        comment_id,
-        &CommentUpdateForm::builder().deleted(Some(deleted)).build(),
-      )
-    })
-    .await?
+    let updated_comment = Comment::update(
+      context.pool(),
+      comment_id,
+      &CommentUpdateForm::builder().deleted(Some(deleted)).build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     let post_id = updated_comment.post_id;
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post = Post::read(context.pool(), post_id).await?;
     let recipient_ids = send_local_notifs(
       vec![],
       &updated_comment,
@@ -94,10 +89,7 @@ impl PerformCrud for DeleteComment {
     .await?;
 
     // Send the apub message
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, orig_comment.post.community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), orig_comment.post.community_id).await?;
     let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
     send_apub_delete_in_community(
       local_user_view.person,
diff --git a/crates/api_crud/src/comment/list.rs b/crates/api_crud/src/comment/list.rs
index 9ab7d6d0..22a6a3ac 100644
--- a/crates/api_crud/src/comment/list.rs
+++ b/crates/api_crud/src/comment/list.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{GetComments, GetCommentsResponse},
   utils::{
-    blocking,
     check_private_instance,
     get_local_user_view_from_jwt_opt,
     listing_type_with_site_default,
@@ -32,7 +31,7 @@ impl PerformCrud for GetComments {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
     check_private_instance(&local_user_view, &local_site)?;
 
     let community_id = data.community_id;
@@ -55,11 +54,7 @@ impl PerformCrud for GetComments {
 
     // If a parent_id is given, fetch the comment to get the path
     let parent_path = if let Some(parent_id) = parent_id {
-      Some(
-        blocking(context.pool(), move |conn| Comment::read(conn, parent_id))
-          .await??
-          .path,
-      )
+      Some(Comment::read(context.pool(), parent_id).await?.path)
     } else {
       None
     };
@@ -67,25 +62,23 @@ impl PerformCrud for GetComments {
     let parent_path_cloned = parent_path.to_owned();
     let post_id = data.post_id;
     let local_user = local_user_view.map(|l| l.local_user);
-    let mut comments = blocking(context.pool(), move |conn| {
-      CommentQuery::builder()
-        .conn(conn)
-        .listing_type(Some(listing_type))
-        .sort(sort)
-        .max_depth(max_depth)
-        .saved_only(saved_only)
-        .community_id(community_id)
-        .community_actor_id(community_actor_id)
-        .parent_path(parent_path_cloned)
-        .post_id(post_id)
-        .local_user(local_user.as_ref())
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_get_comments"))?;
+    let mut comments = CommentQuery::builder()
+      .pool(context.pool())
+      .listing_type(Some(listing_type))
+      .sort(sort)
+      .max_depth(max_depth)
+      .saved_only(saved_only)
+      .community_id(community_id)
+      .community_actor_id(community_actor_id)
+      .parent_path(parent_path_cloned)
+      .post_id(post_id)
+      .local_user(local_user.as_ref())
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_get_comments"))?;
 
     // Blank out deleted or removed info
     for cv in comments
diff --git a/crates/api_crud/src/comment/read.rs b/crates/api_crud/src/comment/read.rs
index a4868c09..7d5779ff 100644
--- a/crates/api_crud/src/comment/read.rs
+++ b/crates/api_crud/src/comment/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, GetComment},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_db_views::structs::CommentView;
@@ -23,17 +23,15 @@ impl PerformCrud for GetComment {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
     let person_id = local_user_view.map(|u| u.person.id);
     let id = data.id;
-    let comment_view = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, id, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_comment"))?;
+    let comment_view = CommentView::read(context.pool(), id, person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_comment"))?;
 
     Ok(Self::Response {
       comment_view,
diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs
index 3b94fd47..c866eca3 100644
--- a/crates/api_crud/src/comment/remove.rs
+++ b/crates/api_crud/src/comment/remove.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, RemoveComment},
-  utils::{blocking, check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
+  utils::{check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -37,10 +37,7 @@ impl PerformCrud for RemoveComment {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let comment_id = data.comment_id;
-    let orig_comment = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, None)
-    })
-    .await??;
+    let orig_comment = CommentView::read(context.pool(), comment_id, None).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -59,14 +56,12 @@ impl PerformCrud for RemoveComment {
 
     // Do the remove
     let removed = data.removed;
-    let updated_comment = blocking(context.pool(), move |conn| {
-      Comment::update(
-        conn,
-        comment_id,
-        &CommentUpdateForm::builder().removed(Some(removed)).build(),
-      )
-    })
-    .await?
+    let updated_comment = Comment::update(
+      context.pool(),
+      comment_id,
+      &CommentUpdateForm::builder().removed(Some(removed)).build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     // Mod tables
@@ -76,13 +71,10 @@ impl PerformCrud for RemoveComment {
       removed: Some(removed),
       reason: data.reason.to_owned(),
     };
-    blocking(context.pool(), move |conn| {
-      ModRemoveComment::create(conn, &form)
-    })
-    .await??;
+    ModRemoveComment::create(context.pool(), &form).await?;
 
     let post_id = updated_comment.post_id;
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post = Post::read(context.pool(), post_id).await?;
     let recipient_ids = send_local_notifs(
       vec![],
       &updated_comment,
@@ -105,10 +97,7 @@ impl PerformCrud for RemoveComment {
     .await?;
 
     // Send the apub message
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, orig_comment.post.community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), orig_comment.post.community_id).await?;
     let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
     send_apub_delete_in_community(
       local_user_view.person,
diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs
index 9678765e..ef8aabb0 100644
--- a/crates/api_crud/src/comment/update.rs
+++ b/crates/api_crud/src/comment/update.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   comment::{CommentResponse, EditComment},
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     check_post_deleted_or_removed,
@@ -49,13 +48,10 @@ impl PerformCrud for EditComment {
     let data: &EditComment = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let comment_id = data.comment_id;
-    let orig_comment = blocking(context.pool(), move |conn| {
-      CommentView::read(conn, comment_id, None)
-    })
-    .await??;
+    let orig_comment = CommentView::read(context.pool(), comment_id, None).await?;
 
     // TODO is this necessary? It should really only need to check on create
     check_community_ban(
@@ -83,10 +79,12 @@ impl PerformCrud for EditComment {
     }
 
     let language_id = self.language_id;
-    blocking(context.pool(), move |conn| {
-      CommunityLanguage::is_allowed_community_language(conn, language_id, orig_comment.community.id)
-    })
-    .await??;
+    CommunityLanguage::is_allowed_community_language(
+      context.pool(),
+      language_id,
+      orig_comment.community.id,
+    )
+    .await?;
 
     // Update the Content
     let content_slurs_removed = data
@@ -99,11 +97,9 @@ impl PerformCrud for EditComment {
       .distinguished(data.distinguished)
       .language_id(data.language_id)
       .build();
-    let updated_comment = blocking(context.pool(), move |conn| {
-      Comment::update(conn, comment_id, &form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
+    let updated_comment = Comment::update(context.pool(), comment_id, &form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_comment"))?;
 
     // Do the mentions / recipients
     let updated_comment_content = updated_comment.content.to_owned();
diff --git a/crates/api_crud/src/community/create.rs b/crates/api_crud/src/community/create.rs
index 63cdc3af..128870ea 100644
--- a/crates/api_crud/src/community/create.rs
+++ b/crates/api_crud/src/community/create.rs
@@ -3,7 +3,7 @@ use activitypub_federation::core::{object_id::ObjectId, signatures::generate_act
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, CreateCommunity},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin, local_site_to_slur_regex},
+  utils::{get_local_user_view_from_jwt, is_admin, local_site_to_slur_regex},
 };
 use lemmy_apub::{
   generate_followers_url,
@@ -47,7 +47,7 @@ impl PerformCrud for CreateCommunity {
     let data: &CreateCommunity = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
     let local_site = site_view.local_site;
 
     if local_site.community_creation_admin_only && is_admin(&local_user_view).is_err() {
@@ -101,11 +101,9 @@ impl PerformCrud for CreateCommunity {
       .instance_id(site_view.site.instance_id)
       .build();
 
-    let inserted_community = blocking(context.pool(), move |conn| {
-      Community::create(conn, &community_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "community_already_exists"))?;
+    let inserted_community = Community::create(context.pool(), &community_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "community_already_exists"))?;
 
     // The community creator becomes a moderator
     let community_moderator_form = CommunityModeratorForm {
@@ -113,9 +111,8 @@ impl PerformCrud for CreateCommunity {
       person_id: local_user_view.person.id,
     };
 
-    let join = move |conn: &mut _| CommunityModerator::join(conn, &community_moderator_form);
-    blocking(context.pool(), join)
-      .await?
+    CommunityModerator::join(context.pool(), &community_moderator_form)
+      .await
       .map_err(|e| LemmyError::from_error_message(e, "community_moderator_already_exists"))?;
 
     // Follow your own community
@@ -125,16 +122,13 @@ impl PerformCrud for CreateCommunity {
       pending: false,
     };
 
-    let follow = move |conn: &mut _| CommunityFollower::follow(conn, &community_follower_form);
-    blocking(context.pool(), follow)
-      .await?
+    CommunityFollower::follow(context.pool(), &community_follower_form)
+      .await
       .map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
 
     let person_id = local_user_view.person.id;
-    let community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, inserted_community.id, Some(person_id))
-    })
-    .await??;
+    let community_view =
+      CommunityView::read(context.pool(), inserted_community.id, Some(person_id)).await?;
 
     Ok(CommunityResponse { community_view })
   }
diff --git a/crates/api_crud/src/community/delete.rs b/crates/api_crud/src/community/delete.rs
index dff00696..41f14b52 100644
--- a/crates/api_crud/src/community/delete.rs
+++ b/crates/api_crud/src/community/delete.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, DeleteCommunity},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -29,10 +29,8 @@ impl PerformCrud for DeleteCommunity {
 
     // Fetch the community mods
     let community_id = data.community_id;
-    let community_mods = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await??;
+    let community_mods =
+      CommunityModeratorView::for_community(context.pool(), community_id).await?;
 
     // Make sure deleter is the top mod
     if local_user_view.person.id != community_mods[0].moderator.id {
@@ -42,16 +40,14 @@ impl PerformCrud for DeleteCommunity {
     // Do the delete
     let community_id = data.community_id;
     let deleted = data.deleted;
-    let updated_community = blocking(context.pool(), move |conn| {
-      Community::update(
-        conn,
-        community_id,
-        &CommunityUpdateForm::builder()
-          .deleted(Some(deleted))
-          .build(),
-      )
-    })
-    .await?
+    let updated_community = Community::update(
+      context.pool(),
+      community_id,
+      &CommunityUpdateForm::builder()
+        .deleted(Some(deleted))
+        .build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
 
     let res = send_community_ws_message(
diff --git a/crates/api_crud/src/community/list.rs b/crates/api_crud/src/community/list.rs
index dcf5886a..ab95739a 100644
--- a/crates/api_crud/src/community/list.rs
+++ b/crates/api_crud/src/community/list.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{ListCommunities, ListCommunitiesResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_db_schema::{source::local_site::LocalSite, traits::DeleteableOrRemoveable};
 use lemmy_db_views_actor::community_view::CommunityQuery;
@@ -23,7 +23,7 @@ impl PerformCrud for ListCommunities {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -34,18 +34,16 @@ impl PerformCrud for ListCommunities {
     let page = data.page;
     let limit = data.limit;
     let local_user = local_user_view.map(|l| l.local_user);
-    let mut communities = blocking(context.pool(), move |conn| {
-      CommunityQuery::builder()
-        .conn(conn)
-        .listing_type(listing_type)
-        .sort(sort)
-        .local_user(local_user.as_ref())
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await??;
+    let mut communities = CommunityQuery::builder()
+      .pool(context.pool())
+      .listing_type(listing_type)
+      .sort(sort)
+      .local_user(local_user.as_ref())
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await?;
 
     // Blank out deleted or removed info for non-logged in users
     if person_id.is_none() {
diff --git a/crates/api_crud/src/community/read.rs b/crates/api_crud/src/community/read.rs
index 595f3e2b..b42ad49f 100644
--- a/crates/api_crud/src/community/read.rs
+++ b/crates/api_crud/src/community/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{GetCommunity, GetCommunityResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_apub::{
   fetcher::resolve_actor_identifier,
@@ -36,7 +36,7 @@ impl PerformCrud for GetCommunity {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     if data.name.is_none() && data.id.is_none() {
       return Err(LemmyError::from_message("no_id_given"));
@@ -57,11 +57,9 @@ impl PerformCrud for GetCommunity {
       }
     };
 
-    let mut community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
+    let mut community_view = CommunityView::read(context.pool(), community_id, person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
 
     // Blank out deleted or removed info for non-logged in users
     if person_id.is_none() && (community_view.community.deleted || community_view.community.removed)
@@ -69,11 +67,9 @@ impl PerformCrud for GetCommunity {
       community_view.community = community_view.community.blank_out_deleted_or_removed_info();
     }
 
-    let moderators: Vec<CommunityModeratorView> = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
+    let moderators = CommunityModeratorView::for_community(context.pool(), community_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
 
     let online = context
       .chat_server()
@@ -82,10 +78,7 @@ impl PerformCrud for GetCommunity {
       .unwrap_or(1);
 
     let site_id = instance_actor_id_from_url(community_view.community.actor_id.clone().into());
-    let mut site: Option<Site> = blocking(context.pool(), move |conn| {
-      Site::read_from_apub_id(conn, site_id)
-    })
-    .await??;
+    let mut site = Site::read_from_apub_id(context.pool(), site_id).await?;
     // no need to include metadata for local site (its already available through other endpoints).
     // this also prevents us from leaking the federation private key.
     if let Some(s) = &site {
@@ -95,15 +88,9 @@ impl PerformCrud for GetCommunity {
     }
 
     let community_id = community_view.community.id;
-    let discussion_languages = blocking(context.pool(), move |conn| {
-      CommunityLanguage::read(conn, community_id)
-    })
-    .await??;
+    let discussion_languages = CommunityLanguage::read(context.pool(), community_id).await?;
     let default_post_language = if let Some(user) = local_user_view {
-      blocking(context.pool(), move |conn| {
-        default_post_language(conn, community_id, user.local_user.id)
-      })
-      .await??
+      default_post_language(context.pool(), community_id, user.local_user.id).await?
     } else {
       None
     };
diff --git a/crates/api_crud/src/community/remove.rs b/crates/api_crud/src/community/remove.rs
index be486144..ab747354 100644
--- a/crates/api_crud/src/community/remove.rs
+++ b/crates/api_crud/src/community/remove.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, RemoveCommunity},
-  utils::{blocking, get_local_user_view_from_jwt, is_admin},
+  utils::{get_local_user_view_from_jwt, is_admin},
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -35,16 +35,14 @@ impl PerformCrud for RemoveCommunity {
     // Do the remove
     let community_id = data.community_id;
     let removed = data.removed;
-    let updated_community = blocking(context.pool(), move |conn| {
-      Community::update(
-        conn,
-        community_id,
-        &CommunityUpdateForm::builder()
-          .removed(Some(removed))
-          .build(),
-      )
-    })
-    .await?
+    let updated_community = Community::update(
+      context.pool(),
+      community_id,
+      &CommunityUpdateForm::builder()
+        .removed(Some(removed))
+        .build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
 
     // Mod tables
@@ -56,10 +54,7 @@ impl PerformCrud for RemoveCommunity {
       reason: data.reason.to_owned(),
       expires,
     };
-    blocking(context.pool(), move |conn| {
-      ModRemoveCommunity::create(conn, &form)
-    })
-    .await??;
+    ModRemoveCommunity::create(context.pool(), &form).await?;
 
     let res = send_community_ws_message(
       data.community_id,
diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs
index 82ae4cc8..feb8bc8f 100644
--- a/crates/api_crud/src/community/update.rs
+++ b/crates/api_crud/src/community/update.rs
@@ -2,11 +2,11 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   community::{CommunityResponse, EditCommunity},
-  utils::{blocking, get_local_user_view_from_jwt, local_site_to_slur_regex},
+  utils::{get_local_user_view_from_jwt, local_site_to_slur_regex},
 };
 use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
 use lemmy_db_schema::{
-  newtypes::{LanguageId, PersonId},
+  newtypes::PersonId,
   source::{
     actor_language::{CommunityLanguage, SiteLanguage},
     community::{Community, CommunityUpdateForm},
@@ -32,7 +32,7 @@ impl PerformCrud for EditCommunity {
     let data: &EditCommunity = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let icon = diesel_option_overwrite_to_url(&data.icon)?;
     let banner = diesel_option_overwrite_to_url(&data.banner)?;
@@ -44,29 +44,23 @@ impl PerformCrud for EditCommunity {
 
     // Verify its a mod (only mods can edit it)
     let community_id = data.community_id;
-    let mods: Vec<PersonId> = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-        .map(|v| v.into_iter().map(|m| m.moderator.id).collect())
-    })
-    .await??;
+    let mods: Vec<PersonId> = CommunityModeratorView::for_community(context.pool(), community_id)
+      .await
+      .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?;
     if !mods.contains(&local_user_view.person.id) {
       return Err(LemmyError::from_message("not_a_moderator"));
     }
 
     let community_id = data.community_id;
     if let Some(languages) = data.discussion_languages.clone() {
-      let site_languages: Vec<LanguageId> =
-        blocking(context.pool(), SiteLanguage::read_local).await??;
+      let site_languages = SiteLanguage::read_local(context.pool()).await?;
       // check that community languages are a subset of site languages
       // https://stackoverflow.com/a/64227550
       let is_subset = languages.iter().all(|item| site_languages.contains(item));
       if !is_subset {
         return Err(LemmyError::from_message("language_not_allowed"));
       }
-      blocking(context.pool(), move |conn| {
-        CommunityLanguage::update(conn, languages, community_id)
-      })
-      .await??;
+      CommunityLanguage::update(context.pool(), languages, community_id).await?;
     }
 
     let community_form = CommunityUpdateForm::builder()
@@ -79,11 +73,9 @@ impl PerformCrud for EditCommunity {
       .build();
 
     let community_id = data.community_id;
-    let updated_community = blocking(context.pool(), move |conn| {
-      Community::update(conn, community_id, &community_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
+    let updated_community = Community::update(context.pool(), community_id, &community_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
 
     UpdateCommunity::send(
       updated_community.into(),
diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs
index 2c7f605b..46804441 100644
--- a/crates/api_crud/src/post/create.rs
+++ b/crates/api_crud/src/post/create.rs
@@ -4,7 +4,6 @@ use lemmy_api_common::{
   post::{CreatePost, PostResponse},
   request::fetch_site_data,
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     get_local_user_view_from_jwt,
@@ -53,7 +52,7 @@ impl PerformCrud for CreatePost {
     let data: &CreatePost = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let slur_regex = local_site_to_slur_regex(&local_site);
     check_slurs(&data.name, &slur_regex)?;
@@ -71,15 +70,14 @@ impl PerformCrud for CreatePost {
     check_community_deleted_or_removed(data.community_id, context.pool()).await?;
 
     let community_id = data.community_id;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
     if community.posting_restricted_to_mods {
       let community_id = data.community_id;
-      let is_mod = blocking(context.pool(), move |conn| {
-        CommunityView::is_mod_or_admin(conn, local_user_view.local_user.person_id, community_id)
-      })
+      let is_mod = CommunityView::is_mod_or_admin(
+        context.pool(),
+        local_user_view.local_user.person_id,
+        community_id,
+      )
       .await?;
       if !is_mod {
         return Err(LemmyError::from_message("only_mods_can_post_in_community"));
@@ -96,16 +94,11 @@ impl PerformCrud for CreatePost {
     let language_id = match data.language_id {
       Some(lid) => Some(lid),
       None => {
-        blocking(context.pool(), move |conn| {
-          default_post_language(conn, community_id, local_user_view.local_user.id)
-        })
-        .await??
+        default_post_language(context.pool(), community_id, local_user_view.local_user.id).await?
       }
     };
-    blocking(context.pool(), move |conn| {
-      CommunityLanguage::is_allowed_community_language(conn, language_id, community_id)
-    })
-    .await??;
+    CommunityLanguage::is_allowed_community_language(context.pool(), language_id, community_id)
+      .await?;
 
     let post_form = PostInsertForm::builder()
       .name(data.name.trim().to_owned())
@@ -121,36 +114,33 @@ impl PerformCrud for CreatePost {
       .thumbnail_url(thumbnail_url)
       .build();
 
-    let inserted_post =
-      match blocking(context.pool(), move |conn| Post::create(conn, &post_form)).await? {
-        Ok(post) => post,
-        Err(e) => {
-          let err_type = if e.to_string() == "value too long for type character varying(200)" {
-            "post_title_too_long"
-          } else {
-            "couldnt_create_post"
-          };
+    let inserted_post = match Post::create(context.pool(), &post_form).await {
+      Ok(post) => post,
+      Err(e) => {
+        let err_type = if e.to_string() == "value too long for type character varying(200)" {
+          "post_title_too_long"
+        } else {
+          "couldnt_create_post"
+        };
 
-          return Err(LemmyError::from_error_message(e, err_type));
-        }
-      };
+        return Err(LemmyError::from_error_message(e, err_type));
+      }
+    };
 
     let inserted_post_id = inserted_post.id;
     let protocol_and_hostname = context.settings().get_protocol_and_hostname();
-    let updated_post = blocking(context.pool(), move |conn| -> Result<Post, LemmyError> {
-      let apub_id = generate_local_apub_endpoint(
-        EndpointType::Post,
-        &inserted_post_id.to_string(),
-        &protocol_and_hostname,
-      )?;
-      Ok(Post::update(
-        conn,
-        inserted_post_id,
-        &PostUpdateForm::builder().ap_id(Some(apub_id)).build(),
-      )?)
-    })
-    .await?
-    .map_err(|e| e.with_message("couldnt_create_post"))?;
+    let apub_id = generate_local_apub_endpoint(
+      EndpointType::Post,
+      &inserted_post_id.to_string(),
+      &protocol_and_hostname,
+    )?;
+    let updated_post = Post::update(
+      context.pool(),
+      inserted_post_id,
+      &PostUpdateForm::builder().ap_id(Some(apub_id)).build(),
+    )
+    .await
+    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_post"))?;
 
     // They like their own post by default
     let person_id = local_user_view.person.id;
@@ -161,9 +151,8 @@ impl PerformCrud for CreatePost {
       score: 1,
     };
 
-    let like = move |conn: &mut _| PostLike::like(conn, &like_form);
-    blocking(context.pool(), like)
-      .await?
+    PostLike::like(context.pool(), &like_form)
+      .await
       .map_err(|e| LemmyError::from_error_message(e, "couldnt_like_post"))?;
 
     // Mark the post as read
diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs
index 78e2f49a..a0b93008 100644
--- a/crates/api_crud/src/post/delete.rs
+++ b/crates/api_crud/src/post/delete.rs
@@ -2,12 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{DeletePost, PostResponse},
-  utils::{
-    blocking,
-    check_community_ban,
-    check_community_deleted_or_removed,
-    get_local_user_view_from_jwt,
-  },
+  utils::{check_community_ban, check_community_deleted_or_removed, get_local_user_view_from_jwt},
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -35,7 +30,7 @@ impl PerformCrud for DeletePost {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let post_id = data.post_id;
-    let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let orig_post = Post::read(context.pool(), post_id).await?;
 
     // Dont delete it if its already been deleted.
     if orig_post.deleted == data.deleted {
@@ -58,14 +53,12 @@ impl PerformCrud for DeletePost {
     // Update the post
     let post_id = data.post_id;
     let deleted = data.deleted;
-    let updated_post = blocking(context.pool(), move |conn| {
-      Post::update(
-        conn,
-        post_id,
-        &PostUpdateForm::builder().deleted(Some(deleted)).build(),
-      )
-    })
-    .await??;
+    let updated_post = Post::update(
+      context.pool(),
+      post_id,
+      &PostUpdateForm::builder().deleted(Some(deleted)).build(),
+    )
+    .await?;
 
     let res = send_post_ws_message(
       data.post_id,
@@ -77,10 +70,7 @@ impl PerformCrud for DeletePost {
     .await?;
 
     // apub updates
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, orig_post.community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), orig_post.community_id).await?;
     let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
     send_apub_delete_in_community(
       local_user_view.person,
diff --git a/crates/api_crud/src/post/list.rs b/crates/api_crud/src/post/list.rs
index f7f7b2cc..c3d20d3d 100644
--- a/crates/api_crud/src/post/list.rs
+++ b/crates/api_crud/src/post/list.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   post::{GetPosts, GetPostsResponse},
   utils::{
-    blocking,
     check_private_instance,
     get_local_user_view_from_jwt_opt,
     listing_type_with_site_default,
@@ -32,7 +31,7 @@ impl PerformCrud for GetPosts {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -54,22 +53,20 @@ impl PerformCrud for GetPosts {
     };
     let saved_only = data.saved_only;
 
-    let mut posts = blocking(context.pool(), move |conn| {
-      PostQuery::builder()
-        .conn(conn)
-        .local_user(local_user_view.map(|l| l.local_user).as_ref())
-        .listing_type(Some(listing_type))
-        .sort(sort)
-        .community_id(community_id)
-        .community_actor_id(community_actor_id)
-        .saved_only(saved_only)
-        .page(page)
-        .limit(limit)
-        .build()
-        .list()
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_get_posts"))?;
+    let mut posts = PostQuery::builder()
+      .pool(context.pool())
+      .local_user(local_user_view.map(|l| l.local_user).as_ref())
+      .listing_type(Some(listing_type))
+      .sort(sort)
+      .community_id(community_id)
+      .community_actor_id(community_actor_id)
+      .saved_only(saved_only)
+      .page(page)
+      .limit(limit)
+      .build()
+      .list()
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_get_posts"))?;
 
     // Blank out deleted or removed info for non-logged in users
     if !is_logged_in {
diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs
index 746b8470..5e2582a0 100644
--- a/crates/api_crud/src/post/read.rs
+++ b/crates/api_crud/src/post/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{GetPost, GetPostResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
 };
 use lemmy_db_schema::{
   aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
@@ -28,7 +28,7 @@ impl PerformCrud for GetPost {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -38,19 +38,17 @@ impl PerformCrud for GetPost {
     let post_id = if let Some(id) = data.id {
       id
     } else if let Some(comment_id) = data.comment_id {
-      blocking(context.pool(), move |conn| Comment::read(conn, comment_id))
-        .await?
+      Comment::read(context.pool(), comment_id)
+        .await
         .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?
         .post_id
     } else {
       Err(LemmyError::from_message("couldnt_find_post"))?
     };
 
-    let mut post_view = blocking(context.pool(), move |conn| {
-      PostView::read(conn, post_id, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
+    let mut post_view = PostView::read(context.pool(), post_id, person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
 
     // Mark the post as read
     let post_id = post_view.post.id;
@@ -60,11 +58,9 @@ impl PerformCrud for GetPost {
 
     // Necessary for the sidebar subscribed
     let community_id = post_view.community.id;
-    let mut community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, person_id)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
+    let mut community_view = CommunityView::read(context.pool(), community_id, person_id)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_community"))?;
 
     // Insert into PersonPostAggregates
     // to update the read_comments count
@@ -76,11 +72,9 @@ impl PerformCrud for GetPost {
         read_comments,
         ..PersonPostAggregatesForm::default()
       };
-      blocking(context.pool(), move |conn| {
-        PersonPostAggregates::upsert(conn, &person_post_agg_form)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
+      PersonPostAggregates::upsert(context.pool(), &person_post_agg_form)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_find_post"))?;
     }
 
     // Blank out deleted or removed info for non-logged in users
@@ -94,10 +88,7 @@ impl PerformCrud for GetPost {
       }
     }
 
-    let moderators = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await??;
+    let moderators = CommunityModeratorView::for_community(context.pool(), community_id).await?;
 
     let online = context
       .chat_server()
diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs
index d646a008..8850349c 100644
--- a/crates/api_crud/src/post/remove.rs
+++ b/crates/api_crud/src/post/remove.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   post::{PostResponse, RemovePost},
-  utils::{blocking, check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
+  utils::{check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
 };
 use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
 use lemmy_db_schema::{
@@ -31,7 +31,7 @@ impl PerformCrud for RemovePost {
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
 
     let post_id = data.post_id;
-    let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let orig_post = Post::read(context.pool(), post_id).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -51,14 +51,12 @@ impl PerformCrud for RemovePost {
     // Update the post
     let post_id = data.post_id;
     let removed = data.removed;
-    let updated_post = blocking(context.pool(), move |conn| {
-      Post::update(
-        conn,
-        post_id,
-        &PostUpdateForm::builder().removed(Some(removed)).build(),
-      )
-    })
-    .await??;
+    let updated_post = Post::update(
+      context.pool(),
+      post_id,
+      &PostUpdateForm::builder().removed(Some(removed)).build(),
+    )
+    .await?;
 
     // Mod tables
     let form = ModRemovePostForm {
@@ -67,10 +65,7 @@ impl PerformCrud for RemovePost {
       removed: Some(removed),
       reason: data.reason.to_owned(),
     };
-    blocking(context.pool(), move |conn| {
-      ModRemovePost::create(conn, &form)
-    })
-    .await??;
+    ModRemovePost::create(context.pool(), &form).await?;
 
     let res = send_post_ws_message(
       data.post_id,
@@ -82,10 +77,7 @@ impl PerformCrud for RemovePost {
     .await?;
 
     // apub updates
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, orig_post.community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), orig_post.community_id).await?;
     let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
     send_apub_delete_in_community(
       local_user_view.person,
diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs
index ab9993e6..ff6a10f0 100644
--- a/crates/api_crud/src/post/update.rs
+++ b/crates/api_crud/src/post/update.rs
@@ -4,7 +4,6 @@ use lemmy_api_common::{
   post::{EditPost, PostResponse},
   request::fetch_site_data,
   utils::{
-    blocking,
     check_community_ban,
     check_community_deleted_or_removed,
     get_local_user_view_from_jwt,
@@ -44,7 +43,7 @@ impl PerformCrud for EditPost {
     let data: &EditPost = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let data_url = data.url.as_ref();
 
@@ -64,7 +63,7 @@ impl PerformCrud for EditPost {
     }
 
     let post_id = data.post_id;
-    let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let orig_post = Post::read(context.pool(), post_id).await?;
 
     check_community_ban(
       local_user_view.person.id,
@@ -88,10 +87,12 @@ impl PerformCrud for EditPost {
       .unwrap_or_default();
 
     let language_id = self.language_id;
-    blocking(context.pool(), move |conn| {
-      CommunityLanguage::is_allowed_community_language(conn, language_id, orig_post.community_id)
-    })
-    .await??;
+    CommunityLanguage::is_allowed_community_language(
+      context.pool(),
+      language_id,
+      orig_post.community_id,
+    )
+    .await?;
 
     let post_form = PostUpdateForm::builder()
       .name(data.name.to_owned())
@@ -106,10 +107,7 @@ impl PerformCrud for EditPost {
       .build();
 
     let post_id = data.post_id;
-    let res = blocking(context.pool(), move |conn| {
-      Post::update(conn, post_id, &post_form)
-    })
-    .await?;
+    let res = Post::update(context.pool(), post_id, &post_form).await;
     let updated_post: Post = match res {
       Ok(post) => post,
       Err(e) => {
diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs
index 9eeea66d..c0b784ab 100644
--- a/crates/api_crud/src/private_message/create.rs
+++ b/crates/api_crud/src/private_message/create.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{CreatePrivateMessage, PrivateMessageResponse},
   utils::{
-    blocking,
     check_person_block,
     get_interface_language,
     get_local_user_view_from_jwt,
@@ -43,7 +42,7 @@ impl PerformCrud for CreatePrivateMessage {
     let data: &CreatePrivateMessage = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     let content_slurs_removed = remove_slurs(
       &data.content.to_owned(),
@@ -58,41 +57,33 @@ impl PerformCrud for CreatePrivateMessage {
       .recipient_id(data.recipient_id)
       .build();
 
-    let inserted_private_message = match blocking(context.pool(), move |conn| {
-      PrivateMessage::create(conn, &private_message_form)
-    })
-    .await?
-    {
-      Ok(private_message) => private_message,
-      Err(e) => {
-        return Err(LemmyError::from_error_message(
-          e,
-          "couldnt_create_private_message",
-        ));
-      }
-    };
+    let inserted_private_message =
+      match PrivateMessage::create(context.pool(), &private_message_form).await {
+        Ok(private_message) => private_message,
+        Err(e) => {
+          return Err(LemmyError::from_error_message(
+            e,
+            "couldnt_create_private_message",
+          ));
+        }
+      };
 
     let inserted_private_message_id = inserted_private_message.id;
     let protocol_and_hostname = context.settings().get_protocol_and_hostname();
-    let updated_private_message = blocking(
+    let apub_id = generate_local_apub_endpoint(
+      EndpointType::PrivateMessage,
+      &inserted_private_message_id.to_string(),
+      &protocol_and_hostname,
+    )?;
+    let updated_private_message = PrivateMessage::update(
       context.pool(),
-      move |conn| -> Result<PrivateMessage, LemmyError> {
-        let apub_id = generate_local_apub_endpoint(
-          EndpointType::PrivateMessage,
-          &inserted_private_message_id.to_string(),
-          &protocol_and_hostname,
-        )?;
-        Ok(PrivateMessage::update(
-          conn,
-          inserted_private_message.id,
-          &PrivateMessageUpdateForm::builder()
-            .ap_id(Some(apub_id))
-            .build(),
-        )?)
-      },
+      inserted_private_message.id,
+      &PrivateMessageUpdateForm::builder()
+        .ap_id(Some(apub_id))
+        .build(),
     )
-    .await?
-    .map_err(|e| e.with_message("couldnt_create_private_message"))?;
+    .await
+    .map_err(|e| LemmyError::from_error_message(e, "couldnt_create_private_message"))?;
 
     CreateOrUpdatePrivateMessage::send(
       updated_private_message.into(),
@@ -113,10 +104,7 @@ impl PerformCrud for CreatePrivateMessage {
     // Send email to the local recipient, if one exists
     if res.private_message_view.recipient.local {
       let recipient_id = data.recipient_id;
-      let local_recipient = blocking(context.pool(), move |conn| {
-        LocalUserView::read_person(conn, recipient_id)
-      })
-      .await??;
+      let local_recipient = LocalUserView::read_person(context.pool(), recipient_id).await?;
       let lang = get_interface_language(&local_recipient);
       let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
       send_email_to_user(
diff --git a/crates/api_crud/src/private_message/delete.rs b/crates/api_crud/src/private_message/delete.rs
index 8a348223..51cded6d 100644
--- a/crates/api_crud/src/private_message/delete.rs
+++ b/crates/api_crud/src/private_message/delete.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{DeletePrivateMessage, PrivateMessageResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_apub::activities::deletion::send_apub_delete_private_message;
 use lemmy_db_schema::{
@@ -28,10 +28,7 @@ impl PerformCrud for DeletePrivateMessage {
 
     // Checking permissions
     let private_message_id = data.private_message_id;
-    let orig_private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::read(conn, private_message_id)
-    })
-    .await??;
+    let orig_private_message = PrivateMessage::read(context.pool(), private_message_id).await?;
     if local_user_view.person.id != orig_private_message.creator_id {
       return Err(LemmyError::from_message("no_private_message_edit_allowed"));
     }
@@ -39,16 +36,14 @@ impl PerformCrud for DeletePrivateMessage {
     // Doing the update
     let private_message_id = data.private_message_id;
     let deleted = data.deleted;
-    let updated_private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::update(
-        conn,
-        private_message_id,
-        &PrivateMessageUpdateForm::builder()
-          .deleted(Some(deleted))
-          .build(),
-      )
-    })
-    .await?
+    let updated_private_message = PrivateMessage::update(
+      context.pool(),
+      private_message_id,
+      &PrivateMessageUpdateForm::builder()
+        .deleted(Some(deleted))
+        .build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
 
     // Send the apub update
diff --git a/crates/api_crud/src/private_message/read.rs b/crates/api_crud/src/private_message/read.rs
index cc03c318..7e336c3b 100644
--- a/crates/api_crud/src/private_message/read.rs
+++ b/crates/api_crud/src/private_message/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{GetPrivateMessages, PrivateMessagesResponse},
-  utils::{blocking, get_local_user_view_from_jwt},
+  utils::get_local_user_view_from_jwt,
 };
 use lemmy_db_schema::traits::DeleteableOrRemoveable;
 use lemmy_db_views::private_message_view::PrivateMessageQuery;
@@ -27,17 +27,15 @@ impl PerformCrud for GetPrivateMessages {
     let page = data.page;
     let limit = data.limit;
     let unread_only = data.unread_only;
-    let mut messages = blocking(context.pool(), move |conn| {
-      PrivateMessageQuery::builder()
-        .conn(conn)
-        .recipient_id(person_id)
-        .page(page)
-        .limit(limit)
-        .unread_only(unread_only)
-        .build()
-        .list()
-    })
-    .await??;
+    let mut messages = PrivateMessageQuery::builder()
+      .pool(context.pool())
+      .recipient_id(person_id)
+      .page(page)
+      .limit(limit)
+      .unread_only(unread_only)
+      .build()
+      .list()
+      .await?;
 
     // Messages sent by ourselves should be marked as read. The `read` column in database is only
     // for the recipient, and shouldnt be exposed to sender.
diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs
index 9782b64c..dfe06e8e 100644
--- a/crates/api_crud/src/private_message/update.rs
+++ b/crates/api_crud/src/private_message/update.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   private_message::{EditPrivateMessage, PrivateMessageResponse},
-  utils::{blocking, get_local_user_view_from_jwt, local_site_to_slur_regex},
+  utils::{get_local_user_view_from_jwt, local_site_to_slur_regex},
 };
 use lemmy_apub::protocol::activities::{
   create_or_update::private_message::CreateOrUpdatePrivateMessage,
@@ -32,14 +32,11 @@ impl PerformCrud for EditPrivateMessage {
     let data: &EditPrivateMessage = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Checking permissions
     let private_message_id = data.private_message_id;
-    let orig_private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::read(conn, private_message_id)
-    })
-    .await??;
+    let orig_private_message = PrivateMessage::read(context.pool(), private_message_id).await?;
     if local_user_view.person.id != orig_private_message.creator_id {
       return Err(LemmyError::from_message("no_private_message_edit_allowed"));
     }
@@ -47,17 +44,15 @@ impl PerformCrud for EditPrivateMessage {
     // Doing the update
     let content_slurs_removed = remove_slurs(&data.content, &local_site_to_slur_regex(&local_site));
     let private_message_id = data.private_message_id;
-    let updated_private_message = blocking(context.pool(), move |conn| {
-      PrivateMessage::update(
-        conn,
-        private_message_id,
-        &PrivateMessageUpdateForm::builder()
-          .content(Some(content_slurs_removed))
-          .updated(Some(Some(naive_now())))
-          .build(),
-      )
-    })
-    .await?
+    let updated_private_message = PrivateMessage::update(
+      context.pool(),
+      private_message_id,
+      &PrivateMessageUpdateForm::builder()
+        .content(Some(content_slurs_removed))
+        .updated(Some(Some(naive_now())))
+        .build(),
+    )
+    .await
     .map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
 
     // Send the apub update
diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs
index 5340c657..7a9b0484 100644
--- a/crates/api_crud/src/site/create.rs
+++ b/crates/api_crud/src/site/create.rs
@@ -4,7 +4,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   site::{CreateSite, SiteResponse},
   utils::{
-    blocking,
     get_local_user_view_from_jwt,
     is_admin,
     local_site_to_slur_regex,
@@ -43,7 +42,7 @@ impl PerformCrud for CreateSite {
   ) -> Result<SiteResponse, LemmyError> {
     let data: &CreateSite = self;
 
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     if local_site.site_setup {
       return Err(LemmyError::from_message("site_already_exists"));
@@ -88,10 +87,8 @@ impl PerformCrud for CreateSite {
       .build();
 
     let site_id = local_site.site_id;
-    blocking(context.pool(), move |conn| {
-      Site::update(conn, site_id, &site_form)
-    })
-    .await??;
+
+    Site::update(context.pool(), site_id, &site_form).await?;
 
     let local_site_form = LocalSiteUpdateForm::builder()
       // Set the site setup to true
@@ -120,10 +117,8 @@ impl PerformCrud for CreateSite {
       .captcha_enabled(data.captcha_enabled)
       .captcha_difficulty(data.captcha_difficulty.to_owned())
       .build();
-    blocking(context.pool(), move |conn| {
-      LocalSite::update(conn, &local_site_form)
-    })
-    .await??;
+
+    LocalSite::update(context.pool(), &local_site_form).await?;
 
     let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
       .message(data.rate_limit_message)
@@ -140,12 +135,9 @@ impl PerformCrud for CreateSite {
       .search_per_second(data.rate_limit_search_per_second)
       .build();
 
-    blocking(context.pool(), move |conn| {
-      LocalSiteRateLimit::update(conn, &local_site_rate_limit_form)
-    })
-    .await??;
+    LocalSiteRateLimit::update(context.pool(), &local_site_rate_limit_form).await?;
 
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
 
     Ok(SiteResponse { site_view })
   }
diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs
index 226e24f3..2f4203a0 100644
--- a/crates/api_crud/src/site/read.rs
+++ b/crates/api_crud/src/site/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   site::{GetSite, GetSiteResponse, MyUserInfo},
-  utils::{blocking, build_federated_instances, get_local_user_settings_view_from_jwt_opt},
+  utils::{build_federated_instances, get_local_user_settings_view_from_jwt_opt},
 };
 use lemmy_db_schema::source::{actor_language::SiteLanguage, language::Language};
 use lemmy_db_views::structs::{LocalUserDiscussionLanguageView, SiteView};
@@ -28,9 +28,9 @@ impl PerformCrud for GetSite {
   ) -> Result<GetSiteResponse, LemmyError> {
     let data: &GetSite = self;
 
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
 
-    let admins = blocking(context.pool(), PersonViewSafe::admins).await??;
+    let admins = PersonViewSafe::admins(context.pool()).await?;
 
     let online = context
       .chat_server()
@@ -49,37 +49,28 @@ impl PerformCrud for GetSite {
       let person_id = local_user_view.person.id;
       let local_user_id = local_user_view.local_user.id;
 
-      let follows = blocking(context.pool(), move |conn| {
-        CommunityFollowerView::for_person(conn, person_id)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
+      let follows = CommunityFollowerView::for_person(context.pool(), person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
 
       let person_id = local_user_view.person.id;
-      let community_blocks = blocking(context.pool(), move |conn| {
-        CommunityBlockView::for_person(conn, person_id)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
+      let community_blocks = CommunityBlockView::for_person(context.pool(), person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
 
       let person_id = local_user_view.person.id;
-      let person_blocks = blocking(context.pool(), move |conn| {
-        PersonBlockView::for_person(conn, person_id)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
+      let person_blocks = PersonBlockView::for_person(context.pool(), person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
 
-      let moderates = blocking(context.pool(), move |conn| {
-        CommunityModeratorView::for_person(conn, person_id)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
+      let moderates = CommunityModeratorView::for_person(context.pool(), person_id)
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
 
-      let discussion_languages = blocking(context.pool(), move |conn| {
-        LocalUserDiscussionLanguageView::read_languages(conn, local_user_id)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
+      let discussion_languages =
+        LocalUserDiscussionLanguageView::read_languages(context.pool(), local_user_id)
+          .await
+          .map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
 
       Some(MyUserInfo {
         local_user_view,
@@ -96,8 +87,8 @@ impl PerformCrud for GetSite {
     let federated_instances =
       build_federated_instances(&site_view.local_site, context.pool()).await?;
 
-    let all_languages = blocking(context.pool(), Language::read_all).await??;
-    let discussion_languages = blocking(context.pool(), SiteLanguage::read_local).await??;
+    let all_languages = Language::read_all(context.pool()).await?;
+    let discussion_languages = SiteLanguage::read_local(context.pool()).await?;
 
     Ok(GetSiteResponse {
       site_view,
diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs
index 2f050395..5f22d9f2 100644
--- a/crates/api_crud/src/site/update.rs
+++ b/crates/api_crud/src/site/update.rs
@@ -3,7 +3,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   site::{EditSite, SiteResponse},
   utils::{
-    blocking,
     get_local_user_view_from_jwt,
     is_admin,
     local_site_to_slur_regex,
@@ -46,7 +45,7 @@ impl PerformCrud for EditSite {
     let data: &EditSite = self;
     let local_user_view =
       get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     // Make sure user is an admin
     is_admin(&local_user_view)?;
@@ -75,11 +74,8 @@ impl PerformCrud for EditSite {
 
     let site_id = local_site.site_id;
     if let Some(discussion_languages) = data.discussion_languages.clone() {
-      blocking(context.pool(), move |conn| {
-        let site = Site::read(conn, site_id)?;
-        SiteLanguage::update(conn, discussion_languages, &site)
-      })
-      .await??;
+      let site = Site::read(context.pool(), site_id).await?;
+      SiteLanguage::update(context.pool(), discussion_languages.clone(), &site).await?;
     }
 
     let name = data.name.to_owned();
@@ -92,13 +88,11 @@ impl PerformCrud for EditSite {
       .updated(Some(Some(naive_now())))
       .build();
 
-    blocking(context.pool(), move |conn| {
-      Site::update(conn, local_site.site_id, &site_form)
-    })
-    .await
-    // Ignore errors for all these, so as to not throw errors if no update occurs
-    // Diesel will throw an error for empty update forms
-    .ok();
+    Site::update(context.pool(), site_id, &site_form)
+      .await
+      // Ignore errors for all these, so as to not throw errors if no update occurs
+      // Diesel will throw an error for empty update forms
+      .ok();
 
     let local_site_form = LocalSiteUpdateForm::builder()
       .enable_downvotes(data.enable_downvotes)
@@ -126,11 +120,9 @@ impl PerformCrud for EditSite {
       .captcha_difficulty(data.captcha_difficulty.to_owned())
       .build();
 
-    let update_local_site = blocking(context.pool(), move |conn| {
-      LocalSite::update(conn, &local_site_form)
-    })
-    .await
-    .ok();
+    let update_local_site = LocalSite::update(context.pool(), &local_site_form)
+      .await
+      .ok();
 
     let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder()
       .message(data.rate_limit_message)
@@ -147,23 +139,15 @@ impl PerformCrud for EditSite {
       .search_per_second(data.rate_limit_search_per_second)
       .build();
 
-    blocking(context.pool(), move |conn| {
-      LocalSiteRateLimit::update(conn, &local_site_rate_limit_form)
-    })
-    .await
-    .ok();
+    LocalSiteRateLimit::update(context.pool(), &local_site_rate_limit_form)
+      .await
+      .ok();
 
     // Replace the blocked and allowed instances
     let allowed = data.allowed_instances.to_owned();
-    blocking(context.pool(), move |conn| {
-      FederationAllowList::replace(conn, allowed)
-    })
-    .await??;
+    FederationAllowList::replace(context.pool(), allowed).await?;
     let blocked = data.blocked_instances.to_owned();
-    blocking(context.pool(), move |conn| {
-      FederationBlockList::replace(conn, blocked)
-    })
-    .await??;
+    FederationBlockList::replace(context.pool(), blocked).await?;
 
     // TODO can't think of a better way to do this.
     // If the server suddenly requires email verification, or required applications, no old users
@@ -172,39 +156,25 @@ impl PerformCrud for EditSite {
 
     let new_require_application = update_local_site
       .as_ref()
-      .map(|ols| {
-        ols
-          .as_ref()
-          .map(|ls| ls.require_application)
-          .unwrap_or(false)
-      })
+      .map(|ols| ols.require_application)
       .unwrap_or(false);
     if !local_site.require_application && new_require_application {
-      blocking(context.pool(), move |conn| {
-        LocalUser::set_all_users_registration_applications_accepted(conn)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_registrations_accepted"))?;
+      LocalUser::set_all_users_registration_applications_accepted(context.pool())
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_registrations_accepted"))?;
     }
 
     let new_require_email_verification = update_local_site
       .as_ref()
-      .map(|ols| {
-        ols
-          .as_ref()
-          .map(|ls| ls.require_email_verification)
-          .unwrap_or(false)
-      })
+      .map(|ols| ols.require_email_verification)
       .unwrap_or(false);
     if !local_site.require_email_verification && new_require_email_verification {
-      blocking(context.pool(), move |conn| {
-        LocalUser::set_all_users_email_verified(conn)
-      })
-      .await?
-      .map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_email_verified"))?;
+      LocalUser::set_all_users_email_verified(context.pool())
+        .await
+        .map_err(|e| LemmyError::from_error_message(e, "couldnt_set_all_email_verified"))?;
     }
 
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
 
     let res = SiteResponse { site_view };
 
diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs
index 88bc43d0..7cd34fc4 100644
--- a/crates/api_crud/src/user/create.rs
+++ b/crates/api_crud/src/user/create.rs
@@ -4,7 +4,6 @@ use actix_web::web::Data;
 use lemmy_api_common::{
   person::{LoginResponse, Register},
   utils::{
-    blocking,
     honeypot_check,
     local_site_to_slur_regex,
     password_length_check,
@@ -28,7 +27,6 @@ use lemmy_db_schema::{
   traits::Crud,
 };
 use lemmy_db_views::structs::{LocalUserView, SiteView};
-use lemmy_db_views_actor::structs::PersonViewSafe;
 use lemmy_utils::{
   claims::Claims,
   error::LemmyError,
@@ -49,7 +47,7 @@ impl PerformCrud for Register {
   ) -> Result<LoginResponse, LemmyError> {
     let data: &Register = self;
 
-    let site_view = blocking(context.pool(), SiteView::read_local).await??;
+    let site_view = SiteView::read_local(context.pool()).await?;
     let local_site = site_view.local_site;
 
     if !local_site.open_registration {
@@ -63,7 +61,7 @@ impl PerformCrud for Register {
       return Err(LemmyError::from_message("email_required"));
     }
 
-    if local_site.require_application && data.answer.is_none() {
+    if local_site.site_setup && local_site.require_application && data.answer.is_none() {
       return Err(LemmyError::from_message(
         "registration_application_answer_required",
       ));
@@ -74,14 +72,8 @@ impl PerformCrud for Register {
       return Err(LemmyError::from_message("passwords_dont_match"));
     }
 
-    // Check if there are admins. False if admins exist
-    let no_admins = blocking(context.pool(), move |conn| {
-      PersonViewSafe::admins(conn).map(|a| a.is_empty())
-    })
-    .await??;
-
-    // If its not the admin, check the captcha
-    if !no_admins && local_site.captcha_enabled {
+    // If the site is set up, check the captcha
+    if local_site.site_setup && local_site.captcha_enabled {
       let check = context
         .chat_server()
         .send(CheckCaptcha {
@@ -124,16 +116,15 @@ impl PerformCrud for Register {
       .public_key(actor_keypair.public_key)
       .inbox_url(Some(generate_inbox_url(&actor_id)?))
       .shared_inbox_url(Some(generate_shared_inbox_url(&actor_id)?))
-      .admin(Some(no_admins))
+      // If its the initial site setup, they are an admin
+      .admin(Some(!local_site.site_setup))
       .instance_id(site_view.site.instance_id)
       .build();
 
     // insert the person
-    let inserted_person = blocking(context.pool(), move |conn| {
-      Person::create(conn, &person_form)
-    })
-    .await?
-    .map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
+    let inserted_person = Person::create(context.pool(), &person_form)
+      .await
+      .map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
 
     // Create the local user
     let local_user_form = LocalUserInsertForm::builder()
@@ -143,11 +134,7 @@ impl PerformCrud for Register {
       .show_nsfw(Some(data.show_nsfw))
       .build();
 
-    let inserted_local_user = match blocking(context.pool(), move |conn| {
-      LocalUser::create(conn, &local_user_form)
-    })
-    .await?
-    {
+    let inserted_local_user = match LocalUser::create(context.pool(), &local_user_form).await {
       Ok(lu) => lu,
       Err(e) => {
         let err_type = if e.to_string()
@@ -159,16 +146,13 @@ impl PerformCrud for Register {
         };
 
         // If the local user creation errored, then delete that person
-        blocking(context.pool(), move |conn| {
-          Person::delete(conn, inserted_person.id)
-        })
-        .await??;
+        Person::delete(context.pool(), inserted_person.id).await?;
 
         return Err(LemmyError::from_error_message(e, err_type));
       }
     };
 
-    if local_site.require_application {
+    if local_site.site_setup && local_site.require_application {
       // Create the registration application
       let form = RegistrationApplicationInsertForm {
         local_user_id: inserted_local_user.id,
@@ -176,10 +160,7 @@ impl PerformCrud for Register {
         answer: data.answer.to_owned().expect("must have an answer"),
       };
 
-      blocking(context.pool(), move |conn| {
-        RegistrationApplication::create(conn, &form)
-      })
-      .await??;
+      RegistrationApplication::create(context.pool(), &form).await?;
     }
 
     // Email the admins
@@ -194,8 +175,10 @@ impl PerformCrud for Register {
       verify_email_sent: false,
     };
 
-    // Log the user in directly if email verification and application aren't required
-    if !local_site.require_application && !local_site.require_email_verification {
+    // Log the user in directly if the site is not setup, or email verification and application aren't required
+    if !local_site.site_setup
+      || (!local_site.require_application && !local_site.require_email_verification)
+    {
       login_response.jwt = Some(
         Claims::jwt(
           inserted_local_user.id.0,
diff --git a/crates/api_crud/src/user/read.rs b/crates/api_crud/src/user/read.rs
index 5e6355ce..0352b07a 100644
--- a/crates/api_crud/src/user/read.rs
+++ b/crates/api_crud/src/user/read.rs
@@ -2,7 +2,7 @@ use crate::PerformCrud;
 use actix_web::web::Data;
 use lemmy_api_common::{
   person::{GetPersonDetails, GetPersonDetailsResponse},
-  utils::{blocking, check_private_instance, get_local_user_view_from_jwt_opt},
+  utils::{check_private_instance, get_local_user_view_from_jwt_opt},
 };
 use lemmy_apub::{fetcher::resolve_actor_identifier, objects::person::ApubPerson};
 use lemmy_db_schema::{
@@ -34,7 +34,7 @@ impl PerformCrud for GetPersonDetails {
     let local_user_view =
       get_local_user_view_from_jwt_opt(data.auth.as_ref(), context.pool(), context.secret())
         .await?;
-    let local_site = blocking(context.pool(), LocalSite::read).await??;
+    let local_site = LocalSite::read(context.pool()).await?;
 
     check_private_instance(&local_user_view, &local_site)?;
 
@@ -56,10 +56,7 @@ impl PerformCrud for GetPersonDetails {
 
     // You don't need to return settings for the user, since this comes back with GetSite
     // `my_user`
-    let person_view = blocking(context.pool(), move |conn| {
-      PersonViewSafe::read(conn, person_details_id)
-    })
-    .await??;
+    let person_view = PersonViewSafe::read(context.pool(), person_details_id).await?;
 
     let sort = data.sort;
     let page = data.page;
@@ -69,57 +66,50 @@ impl PerformCrud for GetPersonDetails {
     let local_user = local_user_view.map(|l| l.local_user);
     let local_user_clone = local_user.to_owned();
 
-    let posts = blocking(context.pool(), move |conn| {
-      let posts_query = PostQuery::builder()
-        .conn(conn)
-        .sort(sort)
-        .saved_only(saved_only)
-        .local_user(local_user.as_ref())
-        .community_id(community_id)
-        .page(page)
-        .limit(limit);
+    let posts_query = PostQuery::builder()
+      .pool(context.pool())
+      .sort(sort)
+      .saved_only(saved_only)
+      .local_user(local_user.as_ref())
+      .community_id(community_id)
+      .page(page)
+      .limit(limit);
 
-      // If its saved only, you don't care what creator it was
-      // Or, if its not saved, then you only want it for that specific creator
-      if !saved_only.unwrap_or(false) {
-        posts_query
-          .creator_id(Some(person_details_id))
-          .build()
-          .list()
-      } else {
-        posts_query.build().list()
-      }
-    })
-    .await??;
+    // If its saved only, you don't care what creator it was
+    // Or, if its not saved, then you only want it for that specific creator
+    let posts = if !saved_only.unwrap_or(false) {
+      posts_query
+        .creator_id(Some(person_details_id))
+        .build()
+        .list()
+    } else {
+      posts_query.build().list()
+    }
+    .await?;
 
-    let comments = blocking(context.pool(), move |conn| {
-      let comments_query = CommentQuery::builder()
-        .conn(conn)
-        .local_user(local_user_clone.as_ref())
-        .sort(sort.map(post_to_comment_sort_type))
-        .saved_only(saved_only)
-        .show_deleted_and_removed(Some(false))
-        .community_id(community_id)
-        .page(page)
-        .limit(limit);
+    let comments_query = CommentQuery::builder()
+      .pool(context.pool())
+      .local_user(local_user_clone.as_ref())
+      .sort(sort.map(post_to_comment_sort_type))
+      .saved_only(saved_only)
+      .show_deleted_and_removed(Some(false))
+      .community_id(community_id)
+      .page(page)
+      .limit(limit);
 
-      // If its saved only, you don't care what creator it was
-      // Or, if its not saved, then you only want it for that specific creator
-      if !saved_only.unwrap_or(false) {
-        comments_query
-          .creator_id(Some(person_details_id))
-          .build()
-          .list()
-      } else {
-        comments_query.build().list()
-      }
-    })
-    .await??;
+    // If its saved only, you don't care what creator it was
+    // Or, if its not saved, then you only want it for that specific creator
+    let comments = if !saved_only.unwrap_or(false) {
+      comments_query
+        .creator_id(Some(person_details_id))
+        .build()
+        .list()
+    } else {
+      comments_query.build().list()
+    }
+    .await?;
 
-    let moderates = blocking(context.pool(), move |conn| {
-      CommunityModeratorView::for_person(conn, person_details_id)
-    })
-    .await??;
+    let moderates = CommunityModeratorView::for_person(context.pool(), person_details_id).await?;
 
     // Return the jwt
     Ok(GetPersonDetailsResponse {
diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml
index 81967ee9..3fdd062a 100644
--- a/crates/apub/Cargo.toml
+++ b/crates/apub/Cargo.toml
@@ -21,11 +21,11 @@ lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", featur
 lemmy_api_common = { version = "=0.16.5", path = "../api_common", features = ["full"] }
 lemmy_websocket = { version = "=0.16.5", path = "../websocket" }
 activitypub_federation = "0.2.3"
-diesel = "2.0.0"
+diesel = "2.0.2"
 activitystreams-kinds = "0.2.1"
 chrono = { version = "0.4.22", features = ["serde"], default-features = false }
-serde_json = { version = "1.0.85", features = ["preserve_order"] }
-serde = { version = "1.0.145", features = ["derive"] }
+serde_json = { version = "1.0.87", features = ["preserve_order"] }
+serde = { version = "1.0.147", features = ["derive"] }
 serde_with = "1.14.0"
 actix = "0.13.0"
 actix-web = { version = "4.2.1", default-features = false }
@@ -35,15 +35,16 @@ strum_macros = "0.24.3"
 url = { version = "2.3.1", features = ["serde"] }
 http = "0.2.8"
 http-signature-normalization-actix = { version = "0.6.1", default-features = false, features = ["server", "sha-2"] }
-futures = "0.3.24"
+futures = "0.3.25"
 itertools = "0.10.5"
-uuid = { version = "1.1.2", features = ["serde", "v4"] }
+uuid = { version = "1.2.1", features = ["serde", "v4"] }
 sha2 = "0.10.6"
-async-trait = "0.1.57"
-anyhow = "1.0.65"
+async-trait = "0.1.58"
+anyhow = "1.0.66"
 reqwest = { version = "0.11.12", features = ["json"] }
 html2md = "0.2.13"
 once_cell = "1.15.0"
+tokio = "1.21.2"
 
 [dev-dependencies]
 serial_test = "0.9.0"
diff --git a/crates/apub/src/activities/block/block_user.rs b/crates/apub/src/activities/block/block_user.rs
index bef3b6a2..54084707 100644
--- a/crates/apub/src/activities/block/block_user.rs
+++ b/crates/apub/src/activities/block/block_user.rs
@@ -23,7 +23,7 @@ use activitypub_federation::{
 use activitystreams_kinds::{activity::BlockType, public};
 use anyhow::anyhow;
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::{blocking, remove_user_data, remove_user_data_in_community};
+use lemmy_api_common::utils::{remove_user_data, remove_user_data_in_community};
 use lemmy_db_schema::{
   source::{
     community::{
@@ -126,7 +126,7 @@ impl ActivityHandler for BlockUser {
     verify_is_public(&self.to, &self.cc)?;
     match self
       .target
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?
     {
       SiteOrCommunity::Site(site) => {
@@ -164,29 +164,27 @@ impl ActivityHandler for BlockUser {
     let expires = self.expires.map(|u| u.naive_local());
     let mod_person = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let blocked_person = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let target = self
       .target
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     match target {
       SiteOrCommunity::Site(_site) => {
-        let blocked_person = blocking(context.pool(), move |conn| {
-          Person::update(
-            conn,
-            blocked_person.id,
-            &PersonUpdateForm::builder()
-              .banned(Some(true))
-              .ban_expires(Some(expires))
-              .build(),
-          )
-        })
-        .await??;
+        let blocked_person = Person::update(
+          context.pool(),
+          blocked_person.id,
+          &PersonUpdateForm::builder()
+            .banned(Some(true))
+            .ban_expires(Some(expires))
+            .build(),
+        )
+        .await?;
         if self.remove_data.unwrap_or(false) {
           remove_user_data(
             blocked_person.id,
@@ -205,7 +203,7 @@ impl ActivityHandler for BlockUser {
           banned: Some(true),
           expires,
         };
-        blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??;
+        ModBan::create(context.pool(), &form).await?;
       }
       SiteOrCommunity::Community(community) => {
         let community_user_ban_form = CommunityPersonBanForm {
@@ -213,10 +211,7 @@ impl ActivityHandler for BlockUser {
           person_id: blocked_person.id,
           expires: Some(expires),
         };
-        blocking(context.pool(), move |conn| {
-          CommunityPersonBan::ban(conn, &community_user_ban_form)
-        })
-        .await??;
+        CommunityPersonBan::ban(context.pool(), &community_user_ban_form).await?;
 
         // Also unsubscribe them from the community, if they are subscribed
         let community_follower_form = CommunityFollowerForm {
@@ -224,11 +219,9 @@ impl ActivityHandler for BlockUser {
           person_id: blocked_person.id,
           pending: false,
         };
-        blocking(context.pool(), move |conn: &mut _| {
-          CommunityFollower::unfollow(conn, &community_follower_form)
-        })
-        .await?
-        .ok();
+        CommunityFollower::unfollow(context.pool(), &community_follower_form)
+          .await
+          .ok();
 
         if self.remove_data.unwrap_or(false) {
           remove_user_data_in_community(community.id, blocked_person.id, context.pool()).await?;
@@ -243,10 +236,7 @@ impl ActivityHandler for BlockUser {
           banned: Some(true),
           expires,
         };
-        blocking(context.pool(), move |conn| {
-          ModBanFromCommunity::create(conn, &form)
-        })
-        .await??;
+        ModBanFromCommunity::create(context.pool(), &form).await?;
       }
     }
 
@@ -264,7 +254,7 @@ impl GetCommunity for BlockUser {
   ) -> Result<ApubCommunity, LemmyError> {
     let target = self
       .target
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     match target {
       SiteOrCommunity::Community(c) => Ok(c),
diff --git a/crates/apub/src/activities/block/mod.rs b/crates/apub/src/activities/block/mod.rs
index 386260de..bc2ea77f 100644
--- a/crates/apub/src/activities/block/mod.rs
+++ b/crates/apub/src/activities/block/mod.rs
@@ -5,7 +5,6 @@ use crate::{
 };
 use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::site::Site, utils::DbPool};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -116,8 +115,8 @@ impl SiteOrCommunity {
 
 async fn generate_cc(target: &SiteOrCommunity, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
   Ok(match target {
-    SiteOrCommunity::Site(_) => blocking(pool, Site::read_remote_sites)
-      .await??
+    SiteOrCommunity::Site(_) => Site::read_remote_sites(pool)
+      .await?
       .into_iter()
       .map(|s| s.actor_id.into())
       .collect(),
diff --git a/crates/apub/src/activities/block/undo_block_user.rs b/crates/apub/src/activities/block/undo_block_user.rs
index cd9784f3..f18516f9 100644
--- a/crates/apub/src/activities/block/undo_block_user.rs
+++ b/crates/apub/src/activities/block/undo_block_user.rs
@@ -19,7 +19,6 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use activitystreams_kinds::{activity::UndoType, public};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::{CommunityPersonBan, CommunityPersonBanForm},
@@ -102,7 +101,7 @@ impl ActivityHandler for UndoBlockUser {
     context: &Data<LemmyContext>,
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    let instance = local_instance(context);
+    let instance = local_instance(context).await;
     let expires = self.object.expires.map(|u| u.naive_local());
     let mod_person = self
       .actor
@@ -120,17 +119,15 @@ impl ActivityHandler for UndoBlockUser {
       .await?
     {
       SiteOrCommunity::Site(_site) => {
-        let blocked_person = blocking(context.pool(), move |conn| {
-          Person::update(
-            conn,
-            blocked_person.id,
-            &PersonUpdateForm::builder()
-              .banned(Some(false))
-              .ban_expires(Some(expires))
-              .build(),
-          )
-        })
-        .await??;
+        let blocked_person = Person::update(
+          context.pool(),
+          blocked_person.id,
+          &PersonUpdateForm::builder()
+            .banned(Some(false))
+            .ban_expires(Some(expires))
+            .build(),
+        )
+        .await?;
 
         // write mod log
         let form = ModBanForm {
@@ -140,7 +137,7 @@ impl ActivityHandler for UndoBlockUser {
           banned: Some(false),
           expires,
         };
-        blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??;
+        ModBan::create(context.pool(), &form).await?;
       }
       SiteOrCommunity::Community(community) => {
         let community_user_ban_form = CommunityPersonBanForm {
@@ -148,10 +145,7 @@ impl ActivityHandler for UndoBlockUser {
           person_id: blocked_person.id,
           expires: None,
         };
-        blocking(context.pool(), move |conn: &mut _| {
-          CommunityPersonBan::unban(conn, &community_user_ban_form)
-        })
-        .await??;
+        CommunityPersonBan::unban(context.pool(), &community_user_ban_form).await?;
 
         // write to mod log
         let form = ModBanFromCommunityForm {
@@ -162,10 +156,7 @@ impl ActivityHandler for UndoBlockUser {
           banned: Some(false),
           expires,
         };
-        blocking(context.pool(), move |conn| {
-          ModBanFromCommunity::create(conn, &form)
-        })
-        .await??;
+        ModBanFromCommunity::create(context.pool(), &form).await?;
       }
     }
 
diff --git a/crates/apub/src/activities/community/add_mod.rs b/crates/apub/src/activities/community/add_mod.rs
index 4dbd463b..ba78ec3b 100644
--- a/crates/apub/src/activities/community/add_mod.rs
+++ b/crates/apub/src/activities/community/add_mod.rs
@@ -24,7 +24,6 @@ use activitypub_federation::{
   traits::{ActivityHandler, Actor},
 };
 use activitystreams_kinds::{activity::AddType, public};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::{CommunityModerator, CommunityModeratorForm},
@@ -108,30 +107,25 @@ impl ActivityHandler for AddMod {
     let community = self.get_community(context, request_counter).await?;
     let new_mod = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
 
     // If we had to refetch the community while parsing the activity, then the new mod has already
     // been added. Skip it here as it would result in a duplicate key error.
     let new_mod_id = new_mod.id;
-    let moderated_communities = blocking(context.pool(), move |conn| {
-      CommunityModerator::get_person_moderated_communities(conn, new_mod_id)
-    })
-    .await??;
+    let moderated_communities =
+      CommunityModerator::get_person_moderated_communities(context.pool(), new_mod_id).await?;
     if !moderated_communities.contains(&community.id) {
       let form = CommunityModeratorForm {
         community_id: community.id,
         person_id: new_mod.id,
       };
-      blocking(context.pool(), move |conn| {
-        CommunityModerator::join(conn, &form)
-      })
-      .await??;
+      CommunityModerator::join(context.pool(), &form).await?;
 
       // write mod log
       let actor = self
         .actor
-        .dereference(context, local_instance(context), request_counter)
+        .dereference(context, local_instance(context).await, request_counter)
         .await?;
       let form = ModAddCommunityForm {
         mod_person_id: actor.id,
@@ -139,10 +133,7 @@ impl ActivityHandler for AddMod {
         community_id: community.id,
         removed: Some(false),
       };
-      blocking(context.pool(), move |conn| {
-        ModAddCommunity::create(conn, &form)
-      })
-      .await??;
+      ModAddCommunity::create(context.pool(), &form).await?;
     }
     // TODO: send websocket notification about added mod
     Ok(())
diff --git a/crates/apub/src/activities/community/mod.rs b/crates/apub/src/activities/community/mod.rs
index 85062571..4d96ca4c 100644
--- a/crates/apub/src/activities/community/mod.rs
+++ b/crates/apub/src/activities/community/mod.rs
@@ -46,6 +46,6 @@ async fn get_community_from_moderators_url(
 ) -> Result<ApubCommunity, LemmyError> {
   let community_id = Url::parse(&moderators.to_string().replace("/moderators", ""))?;
   ObjectId::new(community_id)
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await
 }
diff --git a/crates/apub/src/activities/community/remove_mod.rs b/crates/apub/src/activities/community/remove_mod.rs
index ede6a008..82c499e4 100644
--- a/crates/apub/src/activities/community/remove_mod.rs
+++ b/crates/apub/src/activities/community/remove_mod.rs
@@ -24,7 +24,6 @@ use activitypub_federation::{
   traits::{ActivityHandler, Actor},
 };
 use activitystreams_kinds::{activity::RemoveType, public};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::{CommunityModerator, CommunityModeratorForm},
@@ -108,22 +107,19 @@ impl ActivityHandler for RemoveMod {
     let community = self.get_community(context, request_counter).await?;
     let remove_mod = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
 
     let form = CommunityModeratorForm {
       community_id: community.id,
       person_id: remove_mod.id,
     };
-    blocking(context.pool(), move |conn| {
-      CommunityModerator::leave(conn, &form)
-    })
-    .await??;
+    CommunityModerator::leave(context.pool(), &form).await?;
 
     // write mod log
     let actor = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let form = ModAddCommunityForm {
       mod_person_id: actor.id,
@@ -131,10 +127,7 @@ impl ActivityHandler for RemoveMod {
       community_id: community.id,
       removed: Some(true),
     };
-    blocking(context.pool(), move |conn| {
-      ModAddCommunity::create(conn, &form)
-    })
-    .await??;
+    ModAddCommunity::create(context.pool(), &form).await?;
 
     // TODO: send websocket notification about removed mod
     Ok(())
diff --git a/crates/apub/src/activities/community/report.rs b/crates/apub/src/activities/community/report.rs
index c3b50abf..33322bf3 100644
--- a/crates/apub/src/activities/community/report.rs
+++ b/crates/apub/src/activities/community/report.rs
@@ -12,7 +12,7 @@ use activitypub_federation::{
   traits::{ActivityHandler, Actor},
 };
 use activitystreams_kinds::activity::FlagType;
-use lemmy_api_common::{comment::CommentReportResponse, post::PostReportResponse, utils::blocking};
+use lemmy_api_common::{comment::CommentReportResponse, post::PostReportResponse};
 use lemmy_db_schema::{
   source::{
     comment_report::{CommentReport, CommentReportForm},
@@ -75,7 +75,7 @@ impl ActivityHandler for Report {
     request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
     let community = self.to[0]
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     Ok(())
@@ -89,11 +89,11 @@ impl ActivityHandler for Report {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     match self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?
     {
       PostOrComment::Post(post) => {
@@ -106,15 +106,9 @@ impl ActivityHandler for Report {
           original_post_body: post.body.clone(),
         };
 
-        let report = blocking(context.pool(), move |conn| {
-          PostReport::report(conn, &report_form)
-        })
-        .await??;
+        let report = PostReport::report(context.pool(), &report_form).await?;
 
-        let post_report_view = blocking(context.pool(), move |conn| {
-          PostReportView::read(conn, report.id, actor.id)
-        })
-        .await??;
+        let post_report_view = PostReportView::read(context.pool(), report.id, actor.id).await?;
 
         context.chat_server().do_send(SendModRoomMessage {
           op: UserOperation::CreateCommentReport,
@@ -131,15 +125,10 @@ impl ActivityHandler for Report {
           reason: self.summary,
         };
 
-        let report = blocking(context.pool(), move |conn| {
-          CommentReport::report(conn, &report_form)
-        })
-        .await??;
+        let report = CommentReport::report(context.pool(), &report_form).await?;
 
-        let comment_report_view = blocking(context.pool(), move |conn| {
-          CommentReportView::read(conn, report.id, actor.id)
-        })
-        .await??;
+        let comment_report_view =
+          CommentReportView::read(context.pool(), report.id, actor.id).await?;
         let community_id = comment_report_view.community.id;
 
         context.chat_server().do_send(SendModRoomMessage {
diff --git a/crates/apub/src/activities/community/update.rs b/crates/apub/src/activities/community/update.rs
index def4d7a4..f19aafec 100644
--- a/crates/apub/src/activities/community/update.rs
+++ b/crates/apub/src/activities/community/update.rs
@@ -18,7 +18,6 @@ use activitypub_federation::{
   traits::{ActivityHandler, ApubObject},
 };
 use activitystreams_kinds::{activity::UpdateType, public};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::community::Community, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_community_ws_message, LemmyContext, UserOperationCrud};
@@ -100,10 +99,8 @@ impl ActivityHandler for UpdateCommunity {
 
     let community_update_form = self.object.into_update_form();
 
-    let updated_community = blocking(context.pool(), move |conn| {
-      Community::update(conn, community.id, &community_update_form)
-    })
-    .await??;
+    let updated_community =
+      Community::update(context.pool(), community.id, &community_update_form).await?;
 
     send_community_ws_message(
       updated_community.id,
@@ -127,7 +124,7 @@ impl GetCommunity for UpdateCommunity {
   ) -> Result<ApubCommunity, LemmyError> {
     let cid = ObjectId::new(self.object.id.clone());
     cid
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await
   }
 }
diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs
index dad6ada9..1c6ce511 100644
--- a/crates/apub/src/activities/create_or_update/comment.rs
+++ b/crates/apub/src/activities/create_or_update/comment.rs
@@ -21,7 +21,7 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use activitystreams_kinds::public;
-use lemmy_api_common::utils::{blocking, check_post_deleted_or_removed};
+use lemmy_api_common::utils::check_post_deleted_or_removed;
 use lemmy_db_schema::{
   source::{
     comment::{CommentLike, CommentLikeForm},
@@ -45,13 +45,9 @@ impl CreateOrUpdateComment {
   ) -> Result<(), LemmyError> {
     // TODO: might be helpful to add a comment method to retrieve community directly
     let post_id = comment.post_id;
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post = Post::read(context.pool(), post_id).await?;
     let community_id = post.community_id;
-    let community: ApubCommunity = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
+    let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
 
     let id = generate_activity_id(
       kind.clone(),
@@ -86,7 +82,7 @@ impl CreateOrUpdateComment {
     let mut inboxes = vec![];
     for t in tagged_users {
       let person = t
-        .dereference(context, local_instance(context), request_counter)
+        .dereference(context, local_instance(context).await, request_counter)
         .await?;
       inboxes.push(person.shared_inbox_or_inbox());
     }
@@ -143,10 +139,7 @@ impl ActivityHandler for CreateOrUpdateComment {
       person_id: comment.creator_id,
       score: 1,
     };
-    blocking(context.pool(), move |conn: &mut _| {
-      CommentLike::like(conn, &like_form)
-    })
-    .await??;
+    CommentLike::like(context.pool(), &like_form).await?;
 
     let do_send_email = self.kind == CreateOrUpdateType::Create;
     let recipients = get_comment_notif_recipients(
@@ -178,10 +171,7 @@ impl GetCommunity for CreateOrUpdateComment {
     request_counter: &mut i32,
   ) -> Result<ApubCommunity, LemmyError> {
     let post = self.object.get_parents(context, request_counter).await?.0;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, post.community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), post.community_id).await?;
     Ok(community.into())
   }
 }
diff --git a/crates/apub/src/activities/create_or_update/mod.rs b/crates/apub/src/activities/create_or_update/mod.rs
index c0854089..a41912da 100644
--- a/crates/apub/src/activities/create_or_update/mod.rs
+++ b/crates/apub/src/activities/create_or_update/mod.rs
@@ -1,6 +1,5 @@
 use crate::{local_instance, objects::person::ApubPerson};
 use activitypub_federation::core::object_id::ObjectId;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   newtypes::LocalUserId,
   source::{comment::Comment, post::Post},
@@ -22,9 +21,9 @@ async fn get_comment_notif_recipients(
   request_counter: &mut i32,
 ) -> Result<Vec<LocalUserId>, LemmyError> {
   let post_id = comment.post_id;
-  let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+  let post = Post::read(context.pool(), post_id).await?;
   let actor = actor
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await?;
 
   // Note:
diff --git a/crates/apub/src/activities/create_or_update/post.rs b/crates/apub/src/activities/create_or_update/post.rs
index d9d7b854..09e9ae0d 100644
--- a/crates/apub/src/activities/create_or_update/post.rs
+++ b/crates/apub/src/activities/create_or_update/post.rs
@@ -19,7 +19,6 @@ use activitypub_federation::{
   utils::{verify_domains_match, verify_urls_match},
 };
 use activitystreams_kinds::public;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     community::Community,
@@ -62,11 +61,7 @@ impl CreateOrUpdatePost {
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let community_id = post.community_id;
-    let community: ApubCommunity = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
+    let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
 
     let create_or_update = CreateOrUpdatePost::new(post, actor, &community, kind, context).await?;
     let activity = AnnouncableActivities::CreateOrUpdatePost(Box::new(create_or_update));
@@ -149,10 +144,7 @@ impl ActivityHandler for CreateOrUpdatePost {
       person_id: post.creator_id,
       score: 1,
     };
-    blocking(context.pool(), move |conn: &mut _| {
-      PostLike::like(conn, &like_form)
-    })
-    .await??;
+    PostLike::like(context.pool(), &like_form).await?;
 
     let notif_type = match self.kind {
       CreateOrUpdateType::Create => UserOperationCrud::CreatePost,
diff --git a/crates/apub/src/activities/create_or_update/private_message.rs b/crates/apub/src/activities/create_or_update/private_message.rs
index 9ad54769..523135db 100644
--- a/crates/apub/src/activities/create_or_update/private_message.rs
+++ b/crates/apub/src/activities/create_or_update/private_message.rs
@@ -13,7 +13,6 @@ use activitypub_federation::{
   traits::{ActivityHandler, Actor, ApubObject},
   utils::verify_domains_match,
 };
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::person::Person, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::{send::send_pm_ws_message, LemmyContext, UserOperationCrud};
@@ -28,10 +27,7 @@ impl CreateOrUpdatePrivateMessage {
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
     let recipient_id = private_message.recipient_id;
-    let recipient: ApubPerson =
-      blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
-        .await??
-        .into();
+    let recipient: ApubPerson = Person::read(context.pool(), recipient_id).await?.into();
 
     let id = generate_activity_id(
       kind.clone(),
diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs
index ca93b89f..0124f233 100644
--- a/crates/apub/src/activities/deletion/delete.rs
+++ b/crates/apub/src/activities/deletion/delete.rs
@@ -11,7 +11,6 @@ use crate::{
 use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::DeleteType;
 use anyhow::anyhow;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     comment::{Comment, CommentUpdateForm},
@@ -76,7 +75,7 @@ impl ActivityHandler for Delete {
       receive_remove_action(
         &self
           .actor
-          .dereference(context, local_instance(context), request_counter)
+          .dereference(context, local_instance(context).await, request_counter)
           .await?,
         self.object.id(),
         reason,
@@ -145,18 +144,13 @@ pub(in crate::activities) async fn receive_remove_action(
         reason,
         expires: None,
       };
-      blocking(context.pool(), move |conn| {
-        ModRemoveCommunity::create(conn, &form)
-      })
-      .await??;
-      let deleted_community = blocking(context.pool(), move |conn| {
-        Community::update(
-          conn,
-          community.id,
-          &CommunityUpdateForm::builder().removed(Some(true)).build(),
-        )
-      })
-      .await??;
+      ModRemoveCommunity::create(context.pool(), &form).await?;
+      let deleted_community = Community::update(
+        context.pool(),
+        community.id,
+        &CommunityUpdateForm::builder().removed(Some(true)).build(),
+      )
+      .await?;
 
       send_community_ws_message(deleted_community.id, RemoveCommunity, None, None, context).await?;
     }
@@ -167,18 +161,13 @@ pub(in crate::activities) async fn receive_remove_action(
         removed: Some(true),
         reason,
       };
-      blocking(context.pool(), move |conn| {
-        ModRemovePost::create(conn, &form)
-      })
-      .await??;
-      let removed_post = blocking(context.pool(), move |conn| {
-        Post::update(
-          conn,
-          post.id,
-          &PostUpdateForm::builder().removed(Some(true)).build(),
-        )
-      })
-      .await??;
+      ModRemovePost::create(context.pool(), &form).await?;
+      let removed_post = Post::update(
+        context.pool(),
+        post.id,
+        &PostUpdateForm::builder().removed(Some(true)).build(),
+      )
+      .await?;
 
       send_post_ws_message(removed_post.id, RemovePost, None, None, context).await?;
     }
@@ -189,18 +178,13 @@ pub(in crate::activities) async fn receive_remove_action(
         removed: Some(true),
         reason,
       };
-      blocking(context.pool(), move |conn| {
-        ModRemoveComment::create(conn, &form)
-      })
-      .await??;
-      let removed_comment = blocking(context.pool(), move |conn| {
-        Comment::update(
-          conn,
-          comment.id,
-          &CommentUpdateForm::builder().removed(Some(true)).build(),
-        )
-      })
-      .await??;
+      ModRemoveComment::create(context.pool(), &form).await?;
+      let removed_comment = Comment::update(
+        context.pool(),
+        comment.id,
+        &CommentUpdateForm::builder().removed(Some(true)).build(),
+      )
+      .await?;
 
       send_comment_ws_message_simple(removed_comment.id, RemoveComment, context).await?;
     }
@@ -220,7 +204,7 @@ impl GetCommunity for Delete {
     let community_id = match DeletableObjects::read_from_db(self.object.id(), context).await? {
       DeletableObjects::Community(c) => c.id,
       DeletableObjects::Comment(c) => {
-        let post = blocking(context.pool(), move |conn| Post::read(conn, c.post_id)).await??;
+        let post = Post::read(context.pool(), c.post_id).await?;
         post.community_id
       }
       DeletableObjects::Post(p) => p.community_id,
@@ -228,10 +212,7 @@ impl GetCommunity for Delete {
         return Err(anyhow!("Private message is not part of community").into())
       }
     };
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
     Ok(community.into())
   }
 }
diff --git a/crates/apub/src/activities/deletion/delete_user.rs b/crates/apub/src/activities/deletion/delete_user.rs
index 9570d85d..08d9d395 100644
--- a/crates/apub/src/activities/deletion/delete_user.rs
+++ b/crates/apub/src/activities/deletion/delete_user.rs
@@ -49,7 +49,7 @@ impl ActivityHandler for DeleteUser {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     delete_user_account(
       actor.id,
diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs
index 0a131c40..73a7edb6 100644
--- a/crates/apub/src/activities/deletion/mod.rs
+++ b/crates/apub/src/activities/deletion/mod.rs
@@ -25,7 +25,6 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use activitystreams_kinds::public;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     comment::{Comment, CommentUpdateForm},
@@ -84,10 +83,7 @@ pub async fn send_apub_delete_private_message(
   context: &LemmyContext,
 ) -> Result<(), LemmyError> {
   let recipient_id = pm.recipient_id;
-  let recipient: ApubPerson =
-    blocking(context.pool(), move |conn| Person::read(conn, recipient_id))
-      .await??
-      .into();
+  let recipient: ApubPerson = Person::read(context.pool(), recipient_id).await?.into();
 
   let deletable = DeletableObjects::PrivateMessage(Box::new(pm.into()));
   let inbox = vec![recipient.shared_inbox_or_inbox()];
@@ -229,7 +225,7 @@ async fn receive_delete_action(
     DeletableObjects::Community(community) => {
       if community.local {
         let mod_: Person = actor
-          .dereference(context, local_instance(context), request_counter)
+          .dereference(context, local_instance(context).await, request_counter)
           .await?
           .deref()
           .clone();
@@ -238,16 +234,14 @@ async fn receive_delete_action(
         send_apub_delete_in_community(mod_, c, object, None, true, context).await?;
       }
 
-      let community = blocking(context.pool(), move |conn| {
-        Community::update(
-          conn,
-          community.id,
-          &CommunityUpdateForm::builder()
-            .deleted(Some(deleted))
-            .build(),
-        )
-      })
-      .await??;
+      let community = Community::update(
+        context.pool(),
+        community.id,
+        &CommunityUpdateForm::builder()
+          .deleted(Some(deleted))
+          .build(),
+      )
+      .await?;
       send_community_ws_message(
         community.id,
         UserOperationCrud::DeleteCommunity,
@@ -259,14 +253,12 @@ async fn receive_delete_action(
     }
     DeletableObjects::Post(post) => {
       if deleted != post.deleted {
-        let deleted_post = blocking(context.pool(), move |conn| {
-          Post::update(
-            conn,
-            post.id,
-            &PostUpdateForm::builder().deleted(Some(deleted)).build(),
-          )
-        })
-        .await??;
+        let deleted_post = Post::update(
+          context.pool(),
+          post.id,
+          &PostUpdateForm::builder().deleted(Some(deleted)).build(),
+        )
+        .await?;
         send_post_ws_message(
           deleted_post.id,
           UserOperationCrud::DeletePost,
@@ -279,14 +271,12 @@ async fn receive_delete_action(
     }
     DeletableObjects::Comment(comment) => {
       if deleted != comment.deleted {
-        let deleted_comment = blocking(context.pool(), move |conn| {
-          Comment::update(
-            conn,
-            comment.id,
-            &CommentUpdateForm::builder().deleted(Some(deleted)).build(),
-          )
-        })
-        .await??;
+        let deleted_comment = Comment::update(
+          context.pool(),
+          comment.id,
+          &CommentUpdateForm::builder().deleted(Some(deleted)).build(),
+        )
+        .await?;
         send_comment_ws_message_simple(
           deleted_comment.id,
           UserOperationCrud::DeleteComment,
@@ -296,16 +286,14 @@ async fn receive_delete_action(
       }
     }
     DeletableObjects::PrivateMessage(pm) => {
-      let deleted_private_message = blocking(context.pool(), move |conn| {
-        PrivateMessage::update(
-          conn,
-          pm.id,
-          &PrivateMessageUpdateForm::builder()
-            .deleted(Some(deleted))
-            .build(),
-        )
-      })
-      .await??;
+      let deleted_private_message = PrivateMessage::update(
+        context.pool(),
+        pm.id,
+        &PrivateMessageUpdateForm::builder()
+          .deleted(Some(deleted))
+          .build(),
+      )
+      .await?;
 
       send_pm_ws_message(
         deleted_private_message.id,
diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs
index 1576e944..29f75e6d 100644
--- a/crates/apub/src/activities/deletion/undo_delete.rs
+++ b/crates/apub/src/activities/deletion/undo_delete.rs
@@ -10,7 +10,6 @@ use crate::{
 };
 use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use activitystreams_kinds::activity::UndoType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     comment::{Comment, CommentUpdateForm},
@@ -75,7 +74,7 @@ impl ActivityHandler for UndoDelete {
       UndoDelete::receive_undo_remove_action(
         &self
           .actor
-          .dereference(context, local_instance(context), request_counter)
+          .dereference(context, local_instance(context).await, request_counter)
           .await?,
         self.object.object.id(),
         context,
@@ -143,18 +142,13 @@ impl UndoDelete {
           reason: None,
           expires: None,
         };
-        blocking(context.pool(), move |conn| {
-          ModRemoveCommunity::create(conn, &form)
-        })
-        .await??;
-        let deleted_community = blocking(context.pool(), move |conn| {
-          Community::update(
-            conn,
-            community.id,
-            &CommunityUpdateForm::builder().removed(Some(false)).build(),
-          )
-        })
-        .await??;
+        ModRemoveCommunity::create(context.pool(), &form).await?;
+        let deleted_community = Community::update(
+          context.pool(),
+          community.id,
+          &CommunityUpdateForm::builder().removed(Some(false)).build(),
+        )
+        .await?;
         send_community_ws_message(deleted_community.id, EditCommunity, None, None, context).await?;
       }
       DeletableObjects::Post(post) => {
@@ -164,18 +158,13 @@ impl UndoDelete {
           removed: Some(false),
           reason: None,
         };
-        blocking(context.pool(), move |conn| {
-          ModRemovePost::create(conn, &form)
-        })
-        .await??;
-        let removed_post = blocking(context.pool(), move |conn| {
-          Post::update(
-            conn,
-            post.id,
-            &PostUpdateForm::builder().removed(Some(false)).build(),
-          )
-        })
-        .await??;
+        ModRemovePost::create(context.pool(), &form).await?;
+        let removed_post = Post::update(
+          context.pool(),
+          post.id,
+          &PostUpdateForm::builder().removed(Some(false)).build(),
+        )
+        .await?;
         send_post_ws_message(removed_post.id, EditPost, None, None, context).await?;
       }
       DeletableObjects::Comment(comment) => {
@@ -185,18 +174,13 @@ impl UndoDelete {
           removed: Some(false),
           reason: None,
         };
-        blocking(context.pool(), move |conn| {
-          ModRemoveComment::create(conn, &form)
-        })
-        .await??;
-        let removed_comment = blocking(context.pool(), move |conn| {
-          Comment::update(
-            conn,
-            comment.id,
-            &CommentUpdateForm::builder().removed(Some(false)).build(),
-          )
-        })
-        .await??;
+        ModRemoveComment::create(context.pool(), &form).await?;
+        let removed_comment = Comment::update(
+          context.pool(),
+          comment.id,
+          &CommentUpdateForm::builder().removed(Some(false)).build(),
+        )
+        .await?;
         send_comment_ws_message_simple(removed_comment.id, EditComment, context).await?;
       }
       DeletableObjects::PrivateMessage(_) => unimplemented!(),
diff --git a/crates/apub/src/activities/following/accept.rs b/crates/apub/src/activities/following/accept.rs
index f964da08..55a37449 100644
--- a/crates/apub/src/activities/following/accept.rs
+++ b/crates/apub/src/activities/following/accept.rs
@@ -11,7 +11,7 @@ use activitypub_federation::{
   utils::verify_urls_match,
 };
 use activitystreams_kinds::activity::AcceptType;
-use lemmy_api_common::{community::CommunityResponse, utils::blocking};
+use lemmy_api_common::community::CommunityResponse;
 use lemmy_db_schema::{source::community::CommunityFollower, traits::Followable};
 use lemmy_db_views::structs::LocalUserView;
 use lemmy_db_views_actor::structs::CommunityView;
@@ -30,7 +30,7 @@ impl AcceptFollowCommunity {
     let person = follow
       .actor
       .clone()
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let accept = AcceptFollowCommunity {
       actor: ObjectId::new(community.actor_id()),
@@ -80,35 +80,27 @@ impl ActivityHandler for AcceptFollowCommunity {
   ) -> Result<(), LemmyError> {
     let community = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let person = self
       .object
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     // This will throw an error if no follow was requested
     let community_id = community.id;
     let person_id = person.id;
-    blocking(context.pool(), move |conn| {
-      CommunityFollower::follow_accepted(conn, community_id, person_id)
-    })
-    .await??;
+    CommunityFollower::follow_accepted(context.pool(), community_id, person_id).await?;
 
     // Send the Subscribed message over websocket
     // Re-read the community_view to get the new SubscribedType
-    let community_view = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, Some(person_id))
-    })
-    .await??;
+    let community_view = CommunityView::read(context.pool(), community_id, Some(person_id)).await?;
 
     // Get the local_user_id
-    let local_recipient_id = blocking(context.pool(), move |conn| {
-      LocalUserView::read_person(conn, person_id)
-    })
-    .await??
-    .local_user
-    .id;
+    let local_recipient_id = LocalUserView::read_person(context.pool(), person_id)
+      .await?
+      .local_user
+      .id;
 
     let response = CommunityResponse { community_view };
 
diff --git a/crates/apub/src/activities/following/follow.rs b/crates/apub/src/activities/following/follow.rs
index b0ae72c7..57390b7f 100644
--- a/crates/apub/src/activities/following/follow.rs
+++ b/crates/apub/src/activities/following/follow.rs
@@ -16,7 +16,6 @@ use activitypub_federation::{
   traits::{ActivityHandler, Actor},
 };
 use activitystreams_kinds::activity::FollowType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
@@ -54,10 +53,9 @@ impl FollowCommunity {
       person_id: actor.id,
       pending: true,
     };
-    blocking(context.pool(), move |conn| {
-      CommunityFollower::follow(conn, &community_follower_form).ok()
-    })
-    .await?;
+    CommunityFollower::follow(context.pool(), &community_follower_form)
+      .await
+      .ok();
 
     let follow = FollowCommunity::new(actor, community, context)?;
     let inbox = vec![community.shared_inbox_or_inbox()];
@@ -87,7 +85,7 @@ impl ActivityHandler for FollowCommunity {
     verify_person(&self.actor, context, request_counter).await?;
     let community = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
     Ok(())
@@ -101,11 +99,11 @@ impl ActivityHandler for FollowCommunity {
   ) -> Result<(), LemmyError> {
     let person = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let community = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let community_follower_form = CommunityFollowerForm {
       community_id: community.id,
@@ -114,10 +112,9 @@ impl ActivityHandler for FollowCommunity {
     };
 
     // This will fail if they're already a follower, but ignore the error.
-    blocking(context.pool(), move |conn| {
-      CommunityFollower::follow(conn, &community_follower_form).ok()
-    })
-    .await?;
+    CommunityFollower::follow(context.pool(), &community_follower_form)
+      .await
+      .ok();
 
     AcceptFollowCommunity::send(self, context, request_counter).await
   }
diff --git a/crates/apub/src/activities/following/undo_follow.rs b/crates/apub/src/activities/following/undo_follow.rs
index 94b0b68e..221d8184 100644
--- a/crates/apub/src/activities/following/undo_follow.rs
+++ b/crates/apub/src/activities/following/undo_follow.rs
@@ -12,7 +12,6 @@ use activitypub_federation::{
   utils::verify_urls_match,
 };
 use activitystreams_kinds::activity::UndoType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::community::{CommunityFollower, CommunityFollowerForm},
   traits::Followable,
@@ -77,12 +76,12 @@ impl ActivityHandler for UndoFollowCommunity {
   ) -> Result<(), LemmyError> {
     let person = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let community = self
       .object
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
 
     let community_follower_form = CommunityFollowerForm {
@@ -92,10 +91,9 @@ impl ActivityHandler for UndoFollowCommunity {
     };
 
     // This will fail if they aren't a follower, but ignore the error.
-    blocking(context.pool(), move |conn| {
-      CommunityFollower::unfollow(conn, &community_follower_form).ok()
-    })
-    .await?;
+    CommunityFollower::unfollow(context.pool(), &community_follower_form)
+      .await
+      .ok();
     Ok(())
   }
 }
diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs
index 0c013fbe..3cf9771e 100644
--- a/crates/apub/src/activities/mod.rs
+++ b/crates/apub/src/activities/mod.rs
@@ -13,7 +13,6 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::public;
 use anyhow::anyhow;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   newtypes::CommunityId,
   source::{community::Community, local_site::LocalSite},
@@ -43,7 +42,7 @@ async fn verify_person(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let person = person_id
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await?;
   if person.banned {
     let err = anyhow!("Person {} is banned", person_id);
@@ -62,16 +61,17 @@ pub(crate) async fn verify_person_in_community(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let person = person_id
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await?;
   if person.banned {
     return Err(LemmyError::from_message("Person is banned from site"));
   }
   let person_id = person.id;
   let community_id = community.id;
-  let is_banned =
-    move |conn: &mut _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
-  if blocking(context.pool(), is_banned).await? {
+  let is_banned = CommunityPersonBanView::get(context.pool(), person_id, community_id)
+    .await
+    .is_ok();
+  if is_banned {
     return Err(LemmyError::from_message("Person is banned from community"));
   }
 
@@ -92,13 +92,11 @@ pub(crate) async fn verify_mod_action(
   request_counter: &mut i32,
 ) -> Result<(), LemmyError> {
   let mod_ = mod_id
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await?;
 
-  let is_mod_or_admin = blocking(context.pool(), move |conn| {
-    CommunityView::is_mod_or_admin(conn, mod_.id, community_id)
-  })
-  .await?;
+  let is_mod_or_admin =
+    CommunityView::is_mod_or_admin(context.pool(), mod_.id, community_id).await?;
   if is_mod_or_admin {
     return Ok(());
   }
@@ -170,8 +168,8 @@ where
   ActorT: Actor + ActorType,
   Activity: ActivityHandler<Error = LemmyError>,
 {
-  let federation_enabled = blocking(context.pool(), &LocalSite::read)
-    .await?
+  let federation_enabled = LocalSite::read(context.pool())
+    .await
     .map(|l| l.federation_enabled)
     .unwrap_or(false);
   if !federation_enabled {
@@ -189,7 +187,7 @@ where
     actor.get_public_key(),
     actor.private_key().expect("actor has private key"),
     inbox,
-    local_instance(context),
+    local_instance(context).await,
   )
   .await?;
 
diff --git a/crates/apub/src/activities/voting/mod.rs b/crates/apub/src/activities/voting/mod.rs
index 6744e1c5..bff67efe 100644
--- a/crates/apub/src/activities/voting/mod.rs
+++ b/crates/apub/src/activities/voting/mod.rs
@@ -2,7 +2,6 @@ use crate::{
   objects::{comment::ApubComment, person::ApubPerson, post::ApubPost},
   protocol::activities::voting::vote::VoteType,
 };
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     comment::{CommentLike, CommentLikeForm},
@@ -35,11 +34,8 @@ async fn vote_comment(
     score: vote_type.into(),
   };
   let person_id = actor.id;
-  blocking(context.pool(), move |conn| {
-    CommentLike::remove(conn, person_id, comment_id)?;
-    CommentLike::like(conn, &like_form)
-  })
-  .await??;
+  CommentLike::remove(context.pool(), person_id, comment_id).await?;
+  CommentLike::like(context.pool(), &like_form).await?;
 
   send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?;
   Ok(())
@@ -59,11 +55,8 @@ async fn vote_post(
     score: vote_type.into(),
   };
   let person_id = actor.id;
-  blocking(context.pool(), move |conn| {
-    PostLike::remove(conn, person_id, post_id)?;
-    PostLike::like(conn, &like_form)
-  })
-  .await??;
+  PostLike::remove(context.pool(), person_id, post_id).await?;
+  PostLike::like(context.pool(), &like_form).await?;
 
   send_post_ws_message(post.id, UserOperation::CreatePostLike, None, None, context).await?;
   Ok(())
@@ -77,10 +70,7 @@ async fn undo_vote_comment(
 ) -> Result<(), LemmyError> {
   let comment_id = comment.id;
   let person_id = actor.id;
-  blocking(context.pool(), move |conn| {
-    CommentLike::remove(conn, person_id, comment_id)
-  })
-  .await??;
+  CommentLike::remove(context.pool(), person_id, comment_id).await?;
 
   send_comment_ws_message_simple(comment_id, UserOperation::CreateCommentLike, context).await?;
   Ok(())
@@ -94,10 +84,7 @@ async fn undo_vote_post(
 ) -> Result<(), LemmyError> {
   let post_id = post.id;
   let person_id = actor.id;
-  blocking(context.pool(), move |conn| {
-    PostLike::remove(conn, person_id, post_id)
-  })
-  .await??;
+  PostLike::remove(context.pool(), person_id, post_id).await?;
 
   send_post_ws_message(post_id, UserOperation::CreatePostLike, None, None, context).await?;
   Ok(())
diff --git a/crates/apub/src/activities/voting/undo_vote.rs b/crates/apub/src/activities/voting/undo_vote.rs
index f6fc36a2..9415e547 100644
--- a/crates/apub/src/activities/voting/undo_vote.rs
+++ b/crates/apub/src/activities/voting/undo_vote.rs
@@ -22,7 +22,6 @@ use activitypub_federation::{
   utils::verify_urls_match,
 };
 use activitystreams_kinds::activity::UndoType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::CommunityId, source::community::Community, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -40,11 +39,7 @@ impl UndoVote {
     kind: VoteType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let community: ApubCommunity = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
+    let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
 
     let object = Vote::new(object, actor, kind.clone(), context)?;
     let id = generate_activity_id(
@@ -97,12 +92,12 @@ impl ActivityHandler for UndoVote {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let object = self
       .object
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     match object {
       PostOrComment::Post(p) => undo_vote_post(actor, &p, context).await,
diff --git a/crates/apub/src/activities/voting/vote.rs b/crates/apub/src/activities/voting/vote.rs
index e33c9567..8a022f7d 100644
--- a/crates/apub/src/activities/voting/vote.rs
+++ b/crates/apub/src/activities/voting/vote.rs
@@ -14,7 +14,6 @@ use crate::{
 };
 use activitypub_federation::{core::object_id::ObjectId, data::Data, traits::ActivityHandler};
 use anyhow::anyhow;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   newtypes::CommunityId,
   source::{community::Community, local_site::LocalSite, post::Post},
@@ -50,11 +49,7 @@ impl Vote {
     kind: VoteType,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??
-    .into();
+    let community = Community::read(context.pool(), community_id).await?.into();
     let vote = Vote::new(object, actor, kind, context)?;
 
     let activity = AnnouncableActivities::Vote(vote);
@@ -83,8 +78,8 @@ impl ActivityHandler for Vote {
   ) -> Result<(), LemmyError> {
     let community = self.get_community(context, request_counter).await?;
     verify_person_in_community(&self.actor, &community, context, request_counter).await?;
-    let enable_downvotes = blocking(context.pool(), LocalSite::read)
-      .await?
+    let enable_downvotes = LocalSite::read(context.pool())
+      .await
       .map(|l| l.enable_downvotes)
       .unwrap_or(true);
     if self.kind == VoteType::Dislike && !enable_downvotes {
@@ -101,11 +96,11 @@ impl ActivityHandler for Vote {
   ) -> Result<(), LemmyError> {
     let actor = self
       .actor
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let object = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     match object {
       PostOrComment::Post(p) => vote_post(&self.kind, actor, &p, context).await,
@@ -124,17 +119,13 @@ impl GetCommunity for Vote {
   ) -> Result<ApubCommunity, LemmyError> {
     let object = self
       .object
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let cid = match object {
       PostOrComment::Post(p) => p.community_id,
-      PostOrComment::Comment(c) => {
-        blocking(context.pool(), move |conn| Post::read(conn, c.post_id))
-          .await??
-          .community_id
-      }
+      PostOrComment::Comment(c) => Post::read(context.pool(), c.post_id).await?.community_id,
     };
-    let community = blocking(context.pool(), move |conn| Community::read(conn, cid)).await??;
+    let community = Community::read(context.pool(), cid).await?;
     Ok(community.into())
   }
 }
diff --git a/crates/apub/src/collections/community_moderators.rs b/crates/apub/src/collections/community_moderators.rs
index 3f88010d..3770882f 100644
--- a/crates/apub/src/collections/community_moderators.rs
+++ b/crates/apub/src/collections/community_moderators.rs
@@ -12,7 +12,6 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::collection::OrderedCollectionType;
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::community::{CommunityModerator, CommunityModeratorForm},
   traits::Joinable,
@@ -42,10 +41,7 @@ impl ApubObject for ApubCommunityModerators {
     // Only read from database if its a local community, otherwise fetch over http
     if data.0.local {
       let cid = data.0.id;
-      let moderators = blocking(data.1.pool(), move |conn| {
-        CommunityModeratorView::for_community(conn, cid)
-      })
-      .await??;
+      let moderators = CommunityModeratorView::for_community(data.1.pool(), cid).await?;
       Ok(Some(ApubCommunityModerators(moderators)))
     } else {
       Ok(None)
@@ -89,10 +85,8 @@ impl ApubObject for ApubCommunityModerators {
     request_counter: &mut i32,
   ) -> Result<Self, LemmyError> {
     let community_id = data.0.id;
-    let current_moderators = blocking(data.1.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await??;
+    let current_moderators =
+      CommunityModeratorView::for_community(data.1.pool(), community_id).await?;
     // Remove old mods from database which arent in the moderators collection anymore
     for mod_user in &current_moderators {
       let mod_id = ObjectId::new(mod_user.moderator.actor_id.clone());
@@ -101,10 +95,7 @@ impl ApubObject for ApubCommunityModerators {
           community_id: mod_user.community.id,
           person_id: mod_user.moderator.id,
         };
-        blocking(data.1.pool(), move |conn| {
-          CommunityModerator::leave(conn, &community_moderator_form)
-        })
-        .await??;
+        CommunityModerator::leave(data.1.pool(), &community_moderator_form).await?;
       }
     }
 
@@ -112,7 +103,7 @@ impl ApubObject for ApubCommunityModerators {
     for mod_id in apub.ordered_items {
       let mod_id = ObjectId::new(mod_id);
       let mod_user: ApubPerson = mod_id
-        .dereference(&data.1, local_instance(&data.1), request_counter)
+        .dereference(&data.1, local_instance(&data.1).await, request_counter)
         .await?;
 
       if !current_moderators
@@ -124,10 +115,7 @@ impl ApubObject for ApubCommunityModerators {
           community_id: data.0.id,
           person_id: mod_user.id,
         };
-        blocking(data.1.pool(), move |conn| {
-          CommunityModerator::join(conn, &community_moderator_form)
-        })
-        .await??;
+        CommunityModerator::join(data.1.pool(), &community_moderator_form).await?;
       }
     }
 
@@ -163,13 +151,14 @@ mod tests {
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_community_moderators() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let (new_mod, site) = parse_lemmy_person(&context).await;
     let community = parse_lemmy_community(&context).await;
     let community_id = community.id;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(context.pool(), "my_domain.tld")
+      .await
+      .unwrap();
 
     let old_mod = PersonInsertForm::builder()
       .name("holly".into())
@@ -177,13 +166,15 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let old_mod = Person::create(conn, &old_mod).unwrap();
+    let old_mod = Person::create(context.pool(), &old_mod).await.unwrap();
     let community_moderator_form = CommunityModeratorForm {
       community_id: community.id,
       person_id: old_mod.id,
     };
 
-    CommunityModerator::join(conn, &community_moderator_form).unwrap();
+    CommunityModerator::join(context.pool(), &community_moderator_form)
+      .await
+      .unwrap();
 
     assert_eq!(site.actor_id.to_string(), "https://enterprise.lemmy.ml/");
 
@@ -191,7 +182,7 @@ mod tests {
       file_to_json_object("assets/lemmy/collections/group_moderators.json").unwrap();
     let url = Url::parse("https://enterprise.lemmy.ml/c/tenforward").unwrap();
     let mut request_counter = 0;
-    let community_context = CommunityContext(community, context);
+    let community_context = CommunityContext(community, context.to_owned());
     ApubCommunityModerators::verify(&json, &url, &community_context, &mut request_counter)
       .await
       .unwrap();
@@ -200,20 +191,21 @@ mod tests {
       .unwrap();
     assert_eq!(request_counter, 0);
 
-    let current_moderators = blocking(community_context.1.pool(), move |conn| {
-      CommunityModeratorView::for_community(conn, community_id)
-    })
-    .await
-    .unwrap()
-    .unwrap();
+    let current_moderators = CommunityModeratorView::for_community(context.pool(), community_id)
+      .await
+      .unwrap();
 
     assert_eq!(current_moderators.len(), 1);
     assert_eq!(current_moderators[0].moderator.id, new_mod.id);
 
-    Person::delete(conn, old_mod.id).unwrap();
-    Person::delete(conn, new_mod.id).unwrap();
-    Community::delete(conn, community_context.0.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Person::delete(context.pool(), old_mod.id).await.unwrap();
+    Person::delete(context.pool(), new_mod.id).await.unwrap();
+    Community::delete(context.pool(), community_context.0.id)
+      .await
+      .unwrap();
+    Site::delete(context.pool(), site.id).await.unwrap();
+    Instance::delete(context.pool(), inserted_instance.id)
+      .await
+      .unwrap();
   }
 }
diff --git a/crates/apub/src/collections/community_outbox.rs b/crates/apub/src/collections/community_outbox.rs
index dde98859..d9fbf4f2 100644
--- a/crates/apub/src/collections/community_outbox.rs
+++ b/crates/apub/src/collections/community_outbox.rs
@@ -16,7 +16,6 @@ use activitypub_federation::{
 use activitystreams_kinds::collection::OrderedCollectionType;
 use chrono::NaiveDateTime;
 use futures::future::join_all;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::source::post::Post;
 use lemmy_utils::error::LemmyError;
 use url::Url;
@@ -42,13 +41,11 @@ impl ApubObject for ApubCommunityOutbox {
     // Only read from database if its a local community, otherwise fetch over http
     if data.0.local {
       let community_id = data.0.id;
-      let post_list: Vec<ApubPost> = blocking(data.1.pool(), move |conn| {
-        Post::list_for_community(conn, community_id)
-      })
-      .await??
-      .into_iter()
-      .map(Into::into)
-      .collect();
+      let post_list: Vec<ApubPost> = Post::list_for_community(data.1.pool(), community_id)
+        .await?
+        .into_iter()
+        .map(Into::into)
+        .collect();
       Ok(Some(ApubCommunityOutbox(post_list)))
     } else {
       Ok(None)
diff --git a/crates/apub/src/fetcher/deletable_apub_object.rs b/crates/apub/src/fetcher/deletable_apub_object.rs
index 2eb4f884..c84ebabb 100644
--- a/crates/apub/src/fetcher/deletable_apub_object.rs
+++ b/crates/apub/src/fetcher/deletable_apub_object.rs
@@ -1,5 +1,4 @@
 use crate::fetcher::post_or_comment::PostOrComment;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_queries::source::{
   comment::Comment_,
   community::Community_,
@@ -27,10 +26,8 @@ pub trait DeletableApubObject {
 impl DeletableApubObject for Community {
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     let id = self.id;
-    blocking(context.pool(), move |conn| {
-      Community::update_deleted(conn, id, true)
-    })
-    .await??;
+      Community::update_deleted(context.pool(), id, true)
+    .await?;
     Ok(())
   }
 }
@@ -39,7 +36,7 @@ impl DeletableApubObject for Community {
 impl DeletableApubObject for Person {
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     let id = self.id;
-    blocking(context.pool(), move |conn| Person::delete_account(conn, id)).await??;
+    Person::delete_account(context.pool(), id).await?;
     Ok(())
   }
 }
@@ -48,10 +45,8 @@ impl DeletableApubObject for Person {
 impl DeletableApubObject for Post {
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     let id = self.id;
-    blocking(context.pool(), move |conn| {
-      Post::update_deleted(conn, id, true)
-    })
-    .await??;
+      Post::update_deleted(context.pool(), id, true)
+    .await?;
     Ok(())
   }
 }
@@ -60,10 +55,8 @@ impl DeletableApubObject for Post {
 impl DeletableApubObject for Comment {
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     let id = self.id;
-    blocking(context.pool(), move |conn| {
-      Comment::update_deleted(conn, id, true)
-    })
-    .await??;
+      Comment::update_deleted(context.pool(), id, true)
+    .await?;
     Ok(())
   }
 }
@@ -73,16 +66,12 @@ impl DeletableApubObject for PostOrComment {
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     match self {
       PostOrComment::Comment(c) => {
-        blocking(context.pool(), move |conn| {
-          Comment::update_deleted(conn, c.id, true)
-        })
-        .await??;
+          Comment::update_deleted(context.pool(), c.id, true)
+        .await?;
       }
       PostOrComment::Post(p) => {
-        blocking(context.pool(), move |conn| {
-          Post::update_deleted(conn, p.id, true)
-        })
-        .await??;
+          Post::update_deleted(context.pool(), p.id, true)
+        .await?;
       }
     }
 
diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs
index edb8a759..d98bb8e4 100644
--- a/crates/apub/src/fetcher/mod.rs
+++ b/crates/apub/src/fetcher/mod.rs
@@ -1,7 +1,6 @@
 use crate::{fetcher::webfinger::webfinger_resolve_actor, ActorType};
 use activitypub_federation::traits::ApubObject;
 use itertools::Itertools;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::traits::ApubActor;
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -37,31 +36,21 @@ where
       .expect("invalid query");
     let name = name.to_string();
     let domain = format!("{}://{}", context.settings().get_protocol_string(), domain);
-    let actor = blocking(context.pool(), move |conn| {
-      DbActor::read_from_name_and_domain(conn, &name, &domain)
-    })
-    .await?;
+    let actor = DbActor::read_from_name_and_domain(context.pool(), &name, &domain).await;
     if actor.is_ok() {
       Ok(actor?)
     } else {
       // Fetch the actor from its home instance using webfinger
       let id = webfinger_resolve_actor::<Actor>(identifier, true, context, &mut 0).await?;
-      let actor: DbActor = blocking(context.pool(), move |conn| {
-        DbActor::read_from_apub_id(conn, &id)
-      })
-      .await??
-      .expect("actor exists as we fetched just before");
+      let actor: DbActor = DbActor::read_from_apub_id(context.pool(), &id)
+        .await?
+        .expect("actor exists as we fetched just before");
       Ok(actor)
     }
   }
   // local actor
   else {
     let identifier = identifier.to_string();
-    Ok(
-      blocking(context.pool(), move |conn| {
-        DbActor::read_from_name(conn, &identifier, include_deleted)
-      })
-      .await??,
-    )
+    Ok(DbActor::read_from_name(context.pool(), &identifier, include_deleted).await?)
   }
 }
diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs
index 3f7eeeab..1daccd3a 100644
--- a/crates/apub/src/fetcher/search.rs
+++ b/crates/apub/src/fetcher/search.rs
@@ -47,7 +47,7 @@ pub async fn search_query_to_object_id(
     object_id.dereference_local(context).await
   } else {
     object_id
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await
   }
 }
diff --git a/crates/apub/src/fetcher/webfinger.rs b/crates/apub/src/fetcher/webfinger.rs
index 0dfdfc22..30ac0e0a 100644
--- a/crates/apub/src/fetcher/webfinger.rs
+++ b/crates/apub/src/fetcher/webfinger.rs
@@ -2,7 +2,6 @@ use crate::{local_instance, ActorType};
 use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
 use anyhow::anyhow;
 use itertools::Itertools;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::DbUrl, source::local_site::LocalSite};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -48,7 +47,7 @@ where
   );
   debug!("Fetching webfinger url: {}", &fetch_url);
 
-  let local_site = blocking(context.pool(), LocalSite::read).await?;
+  let local_site = LocalSite::read(context.pool()).await;
   let http_fetch_retry_limit = local_site
     .as_ref()
     .map(|l| l.federation_http_fetch_retry_limit)
@@ -81,7 +80,7 @@ where
       object_id.dereference_local(context).await
     } else {
       object_id
-        .dereference(context, local_instance(context), request_counter)
+        .dereference(context, local_instance(context).await, request_counter)
         .await
     };
     if object.is_ok() {
diff --git a/crates/apub/src/http/comment.rs b/crates/apub/src/http/comment.rs
index 4a498a16..e2d0fb77 100644
--- a/crates/apub/src/http/comment.rs
+++ b/crates/apub/src/http/comment.rs
@@ -5,7 +5,6 @@ use crate::{
 use activitypub_federation::traits::ApubObject;
 use actix_web::{web, web::Path, HttpResponse};
 use diesel::result::Error::NotFound;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::CommentId, source::comment::Comment, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -23,9 +22,7 @@ pub(crate) async fn get_apub_comment(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
   let id = CommentId(info.comment_id.parse::<i32>()?);
-  let comment: ApubComment = blocking(context.pool(), move |conn| Comment::read(conn, id))
-    .await??
-    .into();
+  let comment: ApubComment = Comment::read(context.pool(), id).await?.into();
   if !comment.local {
     return Err(NotFound.into());
   }
diff --git a/crates/apub/src/http/community.rs b/crates/apub/src/http/community.rs
index d4528236..87a0f1b4 100644
--- a/crates/apub/src/http/community.rs
+++ b/crates/apub/src/http/community.rs
@@ -17,7 +17,6 @@ use activitypub_federation::{
   traits::ApubObject,
 };
 use actix_web::{web, HttpRequest, HttpResponse};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::community::Community, traits::ApubActor};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -34,11 +33,10 @@ pub(crate) async fn get_apub_community_http(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let community: ApubCommunity = blocking(context.pool(), move |conn| {
-    Community::read_from_name(conn, &info.community_name, true)
-  })
-  .await??
-  .into();
+  let community: ApubCommunity =
+    Community::read_from_name(context.pool(), &info.community_name, true)
+      .await?
+      .into();
 
   if !community.deleted && !community.removed {
     let apub = community.into_apub(&**context).await?;
@@ -65,10 +63,7 @@ pub(crate) async fn get_apub_community_followers(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let community = blocking(context.pool(), move |conn| {
-    Community::read_from_name(conn, &info.community_name, false)
-  })
-  .await??;
+  let community = Community::read_from_name(context.pool(), &info.community_name, false).await?;
   let followers = GroupFollowers::new(community, &context).await?;
   Ok(create_apub_response(&followers))
 }
@@ -79,18 +74,14 @@ pub(crate) async fn get_apub_community_outbox(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let community = blocking(context.pool(), move |conn| {
-    Community::read_from_name(conn, &info.community_name, false)
-  })
-  .await??;
+  let community = Community::read_from_name(context.pool(), &info.community_name, false).await?;
   if community.deleted || community.removed {
     return Err(LemmyError::from_message("deleted"));
   }
-
   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
   let outbox_data = CommunityContext(community.into(), context.get_ref().clone());
   let outbox: ApubCommunityOutbox = id
-    .dereference(&outbox_data, local_instance(&context), &mut 0)
+    .dereference(&outbox_data, local_instance(&context).await, &mut 0)
     .await?;
   Ok(create_apub_response(&outbox.into_apub(&outbox_data).await?))
 }
@@ -100,19 +91,17 @@ pub(crate) async fn get_apub_community_moderators(
   info: web::Path<CommunityQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let community: ApubCommunity = blocking(context.pool(), move |conn| {
-    Community::read_from_name(conn, &info.community_name, false)
-  })
-  .await??
-  .into();
+  let community: ApubCommunity =
+    Community::read_from_name(context.pool(), &info.community_name, false)
+      .await?
+      .into();
   if community.deleted || community.removed {
     return Err(LemmyError::from_message("deleted"));
   }
-
   let id = ObjectId::new(generate_outbox_url(&community.actor_id)?);
   let outbox_data = CommunityContext(community, context.get_ref().clone());
   let moderators: ApubCommunityModerators = id
-    .dereference(&outbox_data, local_instance(&context), &mut 0)
+    .dereference(&outbox_data, local_instance(&context).await, &mut 0)
     .await?;
   Ok(create_apub_response(
     &moderators.into_apub(&outbox_data).await?,
diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs
index e2fb0b42..05837f93 100644
--- a/crates/apub/src/http/mod.rs
+++ b/crates/apub/src/http/mod.rs
@@ -15,7 +15,6 @@ use activitypub_federation::{
 };
 use actix_web::{web, HttpRequest, HttpResponse};
 use http::StatusCode;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::source::activity::Activity;
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -71,7 +70,7 @@ where
   receive_activity::<Activity, ActorT, LemmyContext>(
     request,
     activity,
-    local_instance(&context),
+    local_instance(&context).await,
     data,
   )
   .await
@@ -122,10 +121,7 @@ pub(crate) async fn get_activity(
     info.id
   ))?
   .into();
-  let activity = blocking(context.pool(), move |conn| {
-    Activity::read_from_apub_id(conn, &activity_id)
-  })
-  .await??;
+  let activity = Activity::read_from_apub_id(context.pool(), &activity_id).await?;
 
   let sensitive = activity.sensitive.unwrap_or(true);
   if !activity.local || sensitive {
diff --git a/crates/apub/src/http/person.rs b/crates/apub/src/http/person.rs
index 16c937b3..bf82a47c 100644
--- a/crates/apub/src/http/person.rs
+++ b/crates/apub/src/http/person.rs
@@ -8,7 +8,6 @@ use crate::{
 };
 use activitypub_federation::{deser::context::WithContext, traits::ApubObject};
 use actix_web::{web, HttpRequest, HttpResponse};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::person::Person, traits::ApubActor};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -27,11 +26,9 @@ pub(crate) async fn get_apub_person_http(
 ) -> Result<HttpResponse, LemmyError> {
   let user_name = info.into_inner().user_name;
   // TODO: this needs to be able to read deleted persons, so that it can send tombstones
-  let person: ApubPerson = blocking(context.pool(), move |conn| {
-    Person::read_from_name(conn, &user_name, true)
-  })
-  .await??
-  .into();
+  let person: ApubPerson = Person::read_from_name(context.pool(), &user_name, true)
+    .await?
+    .into();
 
   if !person.deleted {
     let apub = person.into_apub(&context).await?;
@@ -59,10 +56,7 @@ pub(crate) async fn get_apub_person_outbox(
   info: web::Path<PersonQuery>,
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let person = blocking(context.pool(), move |conn| {
-    Person::read_from_name(conn, &info.user_name, false)
-  })
-  .await??;
+  let person = Person::read_from_name(context.pool(), &info.user_name, false).await?;
   let outbox_id = generate_outbox_url(&person.actor_id)?.into();
   let outbox = EmptyOutbox::new(outbox_id).await?;
   Ok(create_apub_response(&outbox))
diff --git a/crates/apub/src/http/post.rs b/crates/apub/src/http/post.rs
index 5960db44..5da69fb4 100644
--- a/crates/apub/src/http/post.rs
+++ b/crates/apub/src/http/post.rs
@@ -5,7 +5,6 @@ use crate::{
 use activitypub_federation::traits::ApubObject;
 use actix_web::{web, HttpResponse};
 use diesel::result::Error::NotFound;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::PostId, source::post::Post, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -23,9 +22,7 @@ pub(crate) async fn get_apub_post(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
   let id = PostId(info.post_id.parse::<i32>()?);
-  let post: ApubPost = blocking(context.pool(), move |conn| Post::read(conn, id))
-    .await??
-    .into();
+  let post: ApubPost = Post::read(context.pool(), id).await?.into();
   if !post.local {
     return Err(NotFound.into());
   }
diff --git a/crates/apub/src/http/site.rs b/crates/apub/src/http/site.rs
index 503bc5a9..28eef88a 100644
--- a/crates/apub/src/http/site.rs
+++ b/crates/apub/src/http/site.rs
@@ -6,7 +6,6 @@ use crate::{
 };
 use activitypub_federation::{deser::context::WithContext, traits::ApubObject};
 use actix_web::{web, HttpRequest, HttpResponse};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_views::structs::SiteView;
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -15,10 +14,7 @@ use url::Url;
 pub(crate) async fn get_apub_site_http(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, LemmyError> {
-  let site: ApubSite = blocking(context.pool(), SiteView::read_local)
-    .await??
-    .site
-    .into();
+  let site: ApubSite = SiteView::read_local(context.pool()).await?.site.into();
 
   let apub = site.into_apub(&context).await?;
   Ok(create_apub_response(&apub))
diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs
index 8c7c042c..d8394a6e 100644
--- a/crates/apub/src/lib.rs
+++ b/crates/apub/src/lib.rs
@@ -8,8 +8,6 @@ use activitypub_federation::{
 };
 use anyhow::Context;
 use async_trait::async_trait;
-use diesel::PgConnection;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   newtypes::DbUrl,
   source::{activity::Activity, instance::Instance, local_site::LocalSite},
@@ -17,7 +15,8 @@ use lemmy_db_schema::{
 };
 use lemmy_utils::{error::LemmyError, location_info, settings::structs::Settings};
 use lemmy_websocket::LemmyContext;
-use once_cell::sync::{Lazy, OnceCell};
+use once_cell::sync::Lazy;
+use tokio::sync::OnceCell;
 use url::{ParseError, Url};
 
 pub mod activities;
@@ -35,42 +34,40 @@ static CONTEXT: Lazy<Vec<serde_json::Value>> = Lazy::new(|| {
 
 // TODO: store this in context? but its only used in this crate, no need to expose it elsewhere
 // TODO this singleton needs to be redone to account for live data.
-fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
-  static LOCAL_INSTANCE: OnceCell<LocalInstance> = OnceCell::new();
-  LOCAL_INSTANCE.get_or_init(|| {
-    let conn = &mut context
-      .pool()
-      .get()
-      .expect("getting connection for LOCAL_INSTANCE init");
-    // Local site may be missing
-    let local_site = &LocalSite::read(conn);
-    let worker_count = local_site
-      .as_ref()
-      .map(|l| l.federation_worker_count)
-      .unwrap_or(64) as u64;
-    let http_fetch_retry_limit = local_site
-      .as_ref()
-      .map(|l| l.federation_http_fetch_retry_limit)
-      .unwrap_or(25);
-    let federation_debug = local_site
-      .as_ref()
-      .map(|l| l.federation_debug)
-      .unwrap_or(true);
-
-    let settings = InstanceSettings::builder()
-      .http_fetch_retry_limit(http_fetch_retry_limit)
-      .worker_count(worker_count)
-      .debug(federation_debug)
-      .http_signature_compat(true)
-      .url_verifier(Box::new(VerifyUrlData(context.clone())))
-      .build()
-      .expect("configure federation");
-    LocalInstance::new(
-      context.settings().hostname.to_owned(),
-      context.client().clone(),
-      settings,
-    )
-  })
+async fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
+  static LOCAL_INSTANCE: OnceCell<LocalInstance> = OnceCell::const_new();
+  LOCAL_INSTANCE
+    .get_or_init(|| async {
+      // Local site may be missing
+      let local_site = &LocalSite::read(context.pool()).await;
+      let worker_count = local_site
+        .as_ref()
+        .map(|l| l.federation_worker_count)
+        .unwrap_or(64) as u64;
+      let http_fetch_retry_limit = local_site
+        .as_ref()
+        .map(|l| l.federation_http_fetch_retry_limit)
+        .unwrap_or(25);
+      let federation_debug = local_site
+        .as_ref()
+        .map(|l| l.federation_debug)
+        .unwrap_or(true);
+
+      let settings = InstanceSettings::builder()
+        .http_fetch_retry_limit(http_fetch_retry_limit)
+        .worker_count(worker_count)
+        .debug(federation_debug)
+        .http_signature_compat(true)
+        .url_verifier(Box::new(VerifyUrlData(context.clone())))
+        .build()
+        .expect("configure federation");
+      LocalInstance::new(
+        context.settings().hostname.to_owned(),
+        context.client().clone(),
+        settings,
+      )
+    })
+    .await
 }
 
 #[derive(Clone)]
@@ -79,9 +76,8 @@ struct VerifyUrlData(LemmyContext);
 #[async_trait]
 impl UrlVerifier for VerifyUrlData {
   async fn verify(&self, url: &Url) -> Result<(), &'static str> {
-    let local_site_data = blocking(self.0.pool(), fetch_local_site_data)
+    let local_site_data = fetch_local_site_data(self.0.pool())
       .await
-      .expect("read local site data")
       .expect("read local site data");
     check_apub_id_valid(url, &local_site_data, self.0.settings())
   }
@@ -146,13 +142,13 @@ pub(crate) struct LocalSiteData {
   blocked_instances: Option<Vec<String>>,
 }
 
-pub(crate) fn fetch_local_site_data(
-  conn: &mut PgConnection,
+pub(crate) async fn fetch_local_site_data(
+  pool: &DbPool,
 ) -> Result<LocalSiteData, diesel::result::Error> {
   // LocalSite may be missing
-  let local_site = LocalSite::read(conn).ok();
-  let allowed = Instance::allowlist(conn)?;
-  let blocked = Instance::blocklist(conn)?;
+  let local_site = LocalSite::read(pool).await.ok();
+  let allowed = Instance::allowlist(pool).await?;
+  let blocked = Instance::blocklist(pool).await?;
 
   // These can return empty vectors, so convert them to options
   let allowed_instances = (!allowed.is_empty()).then(|| allowed);
@@ -277,12 +273,7 @@ async fn insert_activity(
   pool: &DbPool,
 ) -> Result<bool, LemmyError> {
   let ap_id = ap_id.to_owned().into();
-  Ok(
-    blocking(pool, move |conn| {
-      Activity::insert(conn, ap_id, activity, local, Some(sensitive))
-    })
-    .await??,
-  )
+  Ok(Activity::insert(pool, ap_id, activity, local, Some(sensitive)).await?)
 }
 
 /// Common methods provided by ActivityPub actors (community and person). Not all methods are
diff --git a/crates/apub/src/mentions.rs b/crates/apub/src/mentions.rs
index aa10658b..8e24270d 100644
--- a/crates/apub/src/mentions.rs
+++ b/crates/apub/src/mentions.rs
@@ -5,7 +5,6 @@ use crate::{
 };
 use activitypub_federation::core::object_id::ObjectId;
 use activitystreams_kinds::link::MentionType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{comment::Comment, person::Person, post::Post},
   traits::Crud,
@@ -104,17 +103,12 @@ async fn get_comment_parent_creator(
   comment: &Comment,
 ) -> Result<ApubPerson, LemmyError> {
   let parent_creator_id = if let Some(parent_comment_id) = comment.parent_comment_id() {
-    let parent_comment =
-      blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
+    let parent_comment = Comment::read(pool, parent_comment_id).await?;
     parent_comment.creator_id
   } else {
     let parent_post_id = comment.post_id;
-    let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
+    let parent_post = Post::read(pool, parent_post_id).await?;
     parent_post.creator_id
   };
-  Ok(
-    blocking(pool, move |conn| Person::read(conn, parent_creator_id))
-      .await??
-      .into(),
-  )
+  Ok(Person::read(pool, parent_creator_id).await?.into())
 }
diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs
index cca092db..ba3e518b 100644
--- a/crates/apub/src/objects/comment.rs
+++ b/crates/apub/src/objects/comment.rs
@@ -19,7 +19,7 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::{object::NoteType, public};
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::{blocking, local_site_opt_to_slur_regex};
+use lemmy_api_common::utils::local_site_opt_to_slur_regex;
 use lemmy_db_schema::{
   source::{
     comment::{Comment, CommentInsertForm, CommentUpdateForm},
@@ -71,22 +71,17 @@ impl ApubObject for ApubComment {
     context: &LemmyContext,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(context.pool(), move |conn| {
-        Comment::read_from_apub_id(conn, object_id)
-      })
-      .await??
-      .map(Into::into),
+      Comment::read_from_apub_id(context.pool(), object_id)
+        .await?
+        .map(Into::into),
     )
   }
 
   #[tracing::instrument(skip_all)]
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     if !self.deleted {
-      blocking(context.pool(), move |conn| {
-        let form = CommentUpdateForm::builder().deleted(Some(true)).build();
-        Comment::update(conn, self.id, &form)
-      })
-      .await??;
+      let form = CommentUpdateForm::builder().deleted(Some(true)).build();
+      Comment::update(context.pool(), self.id, &form).await?;
     }
     Ok(())
   }
@@ -94,19 +89,15 @@ impl ApubObject for ApubComment {
   #[tracing::instrument(skip_all)]
   async fn into_apub(self, context: &LemmyContext) -> Result<Note, LemmyError> {
     let creator_id = self.creator_id;
-    let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
+    let creator = Person::read(context.pool(), creator_id).await?;
 
     let post_id = self.post_id;
-    let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+    let post = Post::read(context.pool(), post_id).await?;
     let community_id = post.community_id;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
 
     let in_reply_to = if let Some(comment_id) = self.parent_comment_id() {
-      let parent_comment =
-        blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??;
+      let parent_comment = Comment::read(context.pool(), comment_id).await?;
       ObjectId::<PostOrComment>::new(parent_comment.ap_id)
     } else {
       ObjectId::<PostOrComment>::new(post.ap_id)
@@ -147,11 +138,8 @@ impl ApubObject for ApubComment {
     verify_is_public(&note.to, &note.cc)?;
     let (post, _) = note.get_parents(context, request_counter).await?;
     let community_id = post.community_id;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    let community = Community::read(context.pool(), community_id).await?;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
 
     check_apub_id_valid_with_strictness(
       note.id.inner(),
@@ -184,13 +172,13 @@ impl ApubObject for ApubComment {
   ) -> Result<ApubComment, LemmyError> {
     let creator = note
       .attributed_to
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let (post, parent_comment) = note.get_parents(context, request_counter).await?;
 
     let content = read_from_string_or_source(&note.content, &note.media_type, &note.source);
 
-    let local_site = blocking(context.pool(), LocalSite::read).await?.ok();
+    let local_site = LocalSite::read(context.pool()).await.ok();
     let slur_regex = &local_site_opt_to_slur_regex(&local_site);
     let content_slurs_removed = remove_slurs(&content, slur_regex);
     let language_id = LanguageTag::to_language_id_single(note.language, context.pool()).await?;
@@ -209,10 +197,7 @@ impl ApubObject for ApubComment {
       language_id,
     };
     let parent_comment_path = parent_comment.map(|t| t.0.path);
-    let comment = blocking(context.pool(), move |conn| {
-      Comment::create(conn, &form, parent_comment_path.as_ref())
-    })
-    .await??;
+    let comment = Comment::create(context.pool(), &form, parent_comment_path.as_ref()).await?;
     Ok(comment.into())
   }
 }
@@ -251,20 +236,18 @@ pub(crate) mod tests {
     (person, community, post, site)
   }
 
-  fn cleanup(data: (ApubPerson, ApubCommunity, ApubPost, ApubSite), context: &LemmyContext) {
-    let conn = &mut context.pool().get().unwrap();
-    Post::delete(conn, data.2.id).unwrap();
-    Community::delete(conn, data.1.id).unwrap();
-    Person::delete(conn, data.0.id).unwrap();
-    Site::delete(conn, data.3.id).unwrap();
-    LocalSite::delete(conn).unwrap();
+  async fn cleanup(data: (ApubPerson, ApubCommunity, ApubPost, ApubSite), context: &LemmyContext) {
+    Post::delete(context.pool(), data.2.id).await.unwrap();
+    Community::delete(context.pool(), data.1.id).await.unwrap();
+    Person::delete(context.pool(), data.0.id).await.unwrap();
+    Site::delete(context.pool(), data.3.id).await.unwrap();
+    LocalSite::delete(context.pool()).await.unwrap();
   }
 
   #[actix_rt::test]
   #[serial]
   pub(crate) async fn test_parse_lemmy_comment() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let url = Url::parse("https://enterprise.lemmy.ml/comment/38741").unwrap();
     let data = prepare_comment_test(&url, &context).await;
 
@@ -286,15 +269,14 @@ pub(crate) mod tests {
     let to_apub = comment.into_apub(&context).await.unwrap();
     assert_json_include!(actual: json, expected: to_apub);
 
-    Comment::delete(conn, comment_id).unwrap();
-    cleanup(data, &context);
+    Comment::delete(context.pool(), comment_id).await.unwrap();
+    cleanup(data, &context).await;
   }
 
   #[actix_rt::test]
   #[serial]
   async fn test_parse_pleroma_comment() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let url = Url::parse("https://enterprise.lemmy.ml/comment/38741").unwrap();
     let data = prepare_comment_test(&url, &context).await;
 
@@ -322,8 +304,8 @@ pub(crate) mod tests {
     assert!(!comment.local);
     assert_eq!(request_counter, 0);
 
-    Comment::delete(conn, comment.id).unwrap();
-    cleanup(data, &context);
+    Comment::delete(context.pool(), comment.id).await.unwrap();
+    cleanup(data, &context).await;
   }
 
   #[actix_rt::test]
diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs
index 6e04f2c1..77c370f1 100644
--- a/crates/apub/src/objects/community.rs
+++ b/crates/apub/src/objects/community.rs
@@ -20,7 +20,6 @@ use activitypub_federation::{
 use activitystreams_kinds::actor::GroupType;
 use chrono::NaiveDateTime;
 use itertools::Itertools;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   source::{
     actor_language::CommunityLanguage,
@@ -72,31 +71,23 @@ impl ApubObject for ApubCommunity {
     context: &LemmyContext,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(context.pool(), move |conn| {
-        Community::read_from_apub_id(conn, &object_id.into())
-      })
-      .await??
-      .map(Into::into),
+      Community::read_from_apub_id(context.pool(), &object_id.into())
+        .await?
+        .map(Into::into),
     )
   }
 
   #[tracing::instrument(skip_all)]
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
-    blocking(context.pool(), move |conn| {
-      let form = CommunityUpdateForm::builder().deleted(Some(true)).build();
-      Community::update(conn, self.id, &form)
-    })
-    .await??;
+    let form = CommunityUpdateForm::builder().deleted(Some(true)).build();
+    Community::update(context.pool(), self.id, &form).await?;
     Ok(())
   }
 
   #[tracing::instrument(skip_all)]
   async fn into_apub(self, data: &LemmyContext) -> Result<Group, LemmyError> {
     let community_id = self.id;
-    let langs = blocking(data.pool(), move |conn| {
-      CommunityLanguage::read(conn, community_id)
-    })
-    .await??;
+    let langs = CommunityLanguage::read(data.pool(), community_id).await?;
     let language = LanguageTag::new_multiple(langs, data.pool()).await?;
 
     let group = Group {
@@ -145,35 +136,29 @@ impl ApubObject for ApubCommunity {
     request_counter: &mut i32,
   ) -> Result<ApubCommunity, LemmyError> {
     let apub_id = group.id.inner().to_owned();
-    let instance = blocking(context.pool(), move |conn| {
-      Instance::create_from_actor_id(conn, &apub_id)
-    })
-    .await??;
+    let instance = Instance::create_from_actor_id(context.pool(), &apub_id).await?;
 
     let form = Group::into_insert_form(group.clone(), instance.id);
     let languages = LanguageTag::to_language_id_multiple(group.language, context.pool()).await?;
 
-    let community: ApubCommunity = blocking(context.pool(), move |conn| {
-      let community = Community::create(conn, &form)?;
-      CommunityLanguage::update(conn, languages, community.id)?;
-      Ok::<Community, diesel::result::Error>(community)
-    })
-    .await??
-    .into();
+    let community = Community::create(context.pool(), &form).await?;
+    CommunityLanguage::update(context.pool(), languages, community.id).await?;
+
+    let community: ApubCommunity = community.into();
     let outbox_data = CommunityContext(community.clone(), context.clone());
 
     // Fetching mods and outbox is not necessary for Lemmy to work, so ignore errors. Besides,
     // we need to ignore these errors so that tests can work entirely offline.
     group
       .outbox
-      .dereference(&outbox_data, local_instance(context), request_counter)
+      .dereference(&outbox_data, local_instance(context).await, request_counter)
       .await
       .map_err(|e| debug!("{}", e))
       .ok();
 
     if let Some(moderators) = &group.moderators {
       moderators
-        .dereference(&outbox_data, local_instance(context), request_counter)
+        .dereference(&outbox_data, local_instance(context).await, request_counter)
         .await
         .map_err(|e| debug!("{}", e))
         .ok();
@@ -217,11 +202,8 @@ impl ApubCommunity {
   ) -> Result<Vec<Url>, LemmyError> {
     let id = self.id;
 
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
-    let follows = blocking(context.pool(), move |conn| {
-      CommunityFollowerView::for_community(conn, id)
-    })
-    .await??;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
+    let follows = CommunityFollowerView::for_community(context.pool(), id).await?;
     let inboxes: Vec<Url> = follows
       .into_iter()
       .filter(|f| !f.follower.local)
@@ -277,8 +259,7 @@ pub(crate) mod tests {
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_community() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let site = parse_lemmy_instance(&context).await;
     let community = parse_lemmy_community(&context).await;
 
@@ -286,7 +267,9 @@ pub(crate) mod tests {
     assert!(!community.local);
     assert_eq!(community.description.as_ref().unwrap().len(), 132);
 
-    Community::delete(conn, community.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
+    Community::delete(context.pool(), community.id)
+      .await
+      .unwrap();
+    Site::delete(context.pool(), site.id).await.unwrap();
   }
 }
diff --git a/crates/apub/src/objects/instance.rs b/crates/apub/src/objects/instance.rs
index de4839ad..e9c70da0 100644
--- a/crates/apub/src/objects/instance.rs
+++ b/crates/apub/src/objects/instance.rs
@@ -20,7 +20,7 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::{blocking, local_site_opt_to_slur_regex};
+use lemmy_api_common::utils::local_site_opt_to_slur_regex;
 use lemmy_db_schema::{
   source::{
     actor_language::SiteLanguage,
@@ -72,11 +72,9 @@ impl ApubObject for ApubSite {
     data: &Self::DataType,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(data.pool(), move |conn| {
-        Site::read_from_apub_id(conn, object_id)
-      })
-      .await??
-      .map(Into::into),
+      Site::read_from_apub_id(data.pool(), object_id)
+        .await?
+        .map(Into::into),
     )
   }
 
@@ -87,7 +85,7 @@ impl ApubObject for ApubSite {
   #[tracing::instrument(skip_all)]
   async fn into_apub(self, data: &Self::DataType) -> Result<Self::ApubType, LemmyError> {
     let site_id = self.id;
-    let langs = blocking(data.pool(), move |conn| SiteLanguage::read(conn, site_id)).await??;
+    let langs = SiteLanguage::read(data.pool(), site_id).await?;
     let language = LanguageTag::new_multiple(langs, data.pool()).await?;
 
     let instance = Instance {
@@ -117,7 +115,7 @@ impl ApubObject for ApubSite {
     data: &Self::DataType,
     _request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    let local_site_data = blocking(data.pool(), fetch_local_site_data).await??;
+    let local_site_data = fetch_local_site_data(data.pool()).await?;
 
     check_apub_id_valid_with_strictness(apub.id.inner(), true, &local_site_data, data.settings())?;
     verify_domains_match(expected_domain, apub.id.inner())?;
@@ -136,10 +134,7 @@ impl ApubObject for ApubSite {
     _request_counter: &mut i32,
   ) -> Result<Self, LemmyError> {
     let apub_id = apub.id.inner().to_owned();
-    let instance = blocking(data.pool(), move |conn| {
-      DbInstance::create_from_actor_id(conn, &apub_id)
-    })
-    .await??;
+    let instance = DbInstance::create_from_actor_id(data.pool(), &apub_id).await?;
 
     let site_form = SiteInsertForm {
       name: apub.name.clone(),
@@ -157,12 +152,8 @@ impl ApubObject for ApubSite {
     };
     let languages = LanguageTag::to_language_id_multiple(apub.language, data.pool()).await?;
 
-    let site = blocking(data.pool(), move |conn| {
-      let site = Site::create(conn, &site_form)?;
-      SiteLanguage::update(conn, languages, &site)?;
-      Ok::<Site, diesel::result::Error>(site)
-    })
-    .await??;
+    let site = Site::create(data.pool(), &site_form).await?;
+    SiteLanguage::update(data.pool(), languages, &site).await?;
     Ok(site.into())
   }
 }
@@ -204,7 +195,7 @@ pub(in crate::objects) async fn fetch_instance_actor_for_object(
   // try to fetch the instance actor (to make things like instance rules available)
   let instance_id = instance_actor_id_from_url(object_id);
   let site = ObjectId::<ApubSite>::new(instance_id.clone())
-    .dereference(context, local_instance(context), request_counter)
+    .dereference(context, local_instance(context).await, request_counter)
     .await;
   if let Err(e) = site {
     debug!("Failed to dereference site for {}: {}", instance_id, e);
@@ -213,8 +204,8 @@ pub(in crate::objects) async fn fetch_instance_actor_for_object(
 
 pub(crate) async fn remote_instance_inboxes(pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
   Ok(
-    blocking(pool, Site::read_remote_sites)
-      .await??
+    Site::read_remote_sites(pool)
+      .await?
       .into_iter()
       .map(|s| ApubSite::from(s).shared_inbox_or_inbox())
       .collect(),
@@ -245,13 +236,12 @@ pub(crate) mod tests {
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_instance() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let site = parse_lemmy_instance(&context).await;
 
     assert_eq!(site.name, "Enterprise");
     assert_eq!(site.description.as_ref().unwrap().len(), 15);
 
-    Site::delete(conn, site.id).unwrap();
+    Site::delete(context.pool(), site.id).await.unwrap();
   }
 }
diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs
index f54d0756..1e2ac79b 100644
--- a/crates/apub/src/objects/mod.rs
+++ b/crates/apub/src/objects/mod.rs
@@ -56,15 +56,8 @@ pub(crate) fn verify_is_remote_object(id: &Url, settings: &Settings) -> Result<(
 pub(crate) mod tests {
   use actix::Actor;
   use anyhow::anyhow;
-  use diesel::{
-    r2d2::{ConnectionManager, Pool},
-    PgConnection,
-  };
   use lemmy_api_common::request::build_user_agent;
-  use lemmy_db_schema::{
-    source::secret::Secret,
-    utils::{establish_unpooled_connection, get_database_url_from_env},
-  };
+  use lemmy_db_schema::{source::secret::Secret, utils::build_db_pool_for_tests};
   use lemmy_utils::{
     error::LemmyError,
     rate_limit::{rate_limiter::RateLimiter, RateLimit, RateLimitConfig},
@@ -92,9 +85,10 @@ pub(crate) mod tests {
   }
 
   // TODO: would be nice if we didnt have to use a full context for tests.
-  pub(crate) fn init_context() -> LemmyContext {
+  pub(crate) async fn init_context() -> LemmyContext {
     // call this to run migrations
-    establish_unpooled_connection();
+    let pool = build_db_pool_for_tests().await;
+
     let settings = SETTINGS.to_owned();
     let client = Client::builder()
       .user_agent(build_user_agent(&settings))
@@ -106,15 +100,6 @@ pub(crate) mod tests {
       id: 0,
       jwt_secret: "".to_string(),
     };
-    let db_url = match get_database_url_from_env() {
-      Ok(url) => url,
-      Err(_) => settings.get_database_url(),
-    };
-    let manager = ConnectionManager::<PgConnection>::new(&db_url);
-    let pool = Pool::builder()
-      .max_size(settings.database.pool_size)
-      .build(manager)
-      .unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
     async fn x() -> Result<String, LemmyError> {
       Ok("".to_string())
     }
diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs
index 41d6b777..efe2c3ee 100644
--- a/crates/apub/src/objects/person.rs
+++ b/crates/apub/src/objects/person.rs
@@ -19,7 +19,7 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::{blocking, local_site_opt_to_slur_regex};
+use lemmy_api_common::utils::local_site_opt_to_slur_regex;
 use lemmy_db_schema::{
   source::{
     instance::Instance,
@@ -69,21 +69,16 @@ impl ApubObject for ApubPerson {
     context: &LemmyContext,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(context.pool(), move |conn| {
-        DbPerson::read_from_apub_id(conn, &object_id.into())
-      })
-      .await??
-      .map(Into::into),
+      DbPerson::read_from_apub_id(context.pool(), &object_id.into())
+        .await?
+        .map(Into::into),
     )
   }
 
   #[tracing::instrument(skip_all)]
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
-    blocking(context.pool(), move |conn| {
-      let form = PersonUpdateForm::builder().deleted(Some(true)).build();
-      DbPerson::update(conn, self.id, &form)
-    })
-    .await??;
+    let form = PersonUpdateForm::builder().deleted(Some(true)).build();
+    DbPerson::update(context.pool(), self.id, &form).await?;
     Ok(())
   }
 
@@ -124,7 +119,7 @@ impl ApubObject for ApubPerson {
     context: &LemmyContext,
     _request_counter: &mut i32,
   ) -> Result<(), LemmyError> {
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
     let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
 
     check_slurs(&person.preferred_username, slur_regex)?;
@@ -150,10 +145,7 @@ impl ApubObject for ApubPerson {
     request_counter: &mut i32,
   ) -> Result<ApubPerson, LemmyError> {
     let apub_id = person.id.inner().to_owned();
-    let instance = blocking(context.pool(), move |conn| {
-      Instance::create_from_actor_id(conn, &apub_id)
-    })
-    .await??;
+    let instance = Instance::create_from_actor_id(context.pool(), &apub_id).await?;
 
     let person_form = PersonInsertForm {
       name: person.preferred_username,
@@ -178,10 +170,7 @@ impl ApubObject for ApubPerson {
       matrix_user_id: person.matrix_user_id,
       instance_id: instance.id,
     };
-    let person = blocking(context.pool(), move |conn| {
-      DbPerson::create(conn, &person_form)
-    })
-    .await??;
+    let person = DbPerson::create(context.pool(), &person_form).await?;
 
     let actor_id = person.actor_id.clone().into();
     fetch_instance_actor_for_object(actor_id, context, request_counter).await;
@@ -245,20 +234,20 @@ pub(crate) mod tests {
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_person() {
-    let context = init_context();
+    let context = init_context().await;
     let (person, site) = parse_lemmy_person(&context).await;
 
     assert_eq!(person.display_name, Some("Jean-Luc Picard".to_string()));
     assert!(!person.local);
     assert_eq!(person.bio.as_ref().unwrap().len(), 39);
 
-    cleanup((person, site), &context);
+    cleanup((person, site), &context).await;
   }
 
   #[actix_rt::test]
   #[serial]
   async fn test_parse_pleroma_person() {
-    let context = init_context();
+    let context = init_context().await;
 
     // create and parse a fake pleroma instance actor, to avoid network request during test
     let mut json: Instance = file_to_json_object("assets/lemmy/objects/instance.json").unwrap();
@@ -285,12 +274,11 @@ pub(crate) mod tests {
     assert_eq!(request_counter, 0);
     assert_eq!(person.bio.as_ref().unwrap().len(), 873);
 
-    cleanup((person, site), &context);
+    cleanup((person, site), &context).await;
   }
 
-  fn cleanup(data: (ApubPerson, ApubSite), context: &LemmyContext) {
-    let conn = &mut context.pool().get().unwrap();
-    DbPerson::delete(conn, data.0.id).unwrap();
-    Site::delete(conn, data.1.id).unwrap();
+  async fn cleanup(data: (ApubPerson, ApubSite), context: &LemmyContext) {
+    DbPerson::delete(context.pool(), data.0.id).await.unwrap();
+    Site::delete(context.pool(), data.1.id).await.unwrap();
   }
 }
diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs
index ac9b82eb..d6719926 100644
--- a/crates/apub/src/objects/post.rs
+++ b/crates/apub/src/objects/post.rs
@@ -21,10 +21,7 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::public;
 use chrono::NaiveDateTime;
-use lemmy_api_common::{
-  request::fetch_site_data,
-  utils::{blocking, local_site_opt_to_slur_regex},
-};
+use lemmy_api_common::{request::fetch_site_data, utils::local_site_opt_to_slur_regex};
 use lemmy_db_schema::{
   self,
   source::{
@@ -77,22 +74,17 @@ impl ApubObject for ApubPost {
     context: &LemmyContext,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(context.pool(), move |conn| {
-        Post::read_from_apub_id(conn, object_id)
-      })
-      .await??
-      .map(Into::into),
+      Post::read_from_apub_id(context.pool(), object_id)
+        .await?
+        .map(Into::into),
     )
   }
 
   #[tracing::instrument(skip_all)]
   async fn delete(self, context: &LemmyContext) -> Result<(), LemmyError> {
     if !self.deleted {
-      blocking(context.pool(), move |conn| {
-        let form = PostUpdateForm::builder().deleted(Some(true)).build();
-        Post::update(conn, self.id, &form)
-      })
-      .await??;
+      let form = PostUpdateForm::builder().deleted(Some(true)).build();
+      Post::update(context.pool(), self.id, &form).await?;
     }
     Ok(())
   }
@@ -101,12 +93,9 @@ impl ApubObject for ApubPost {
   #[tracing::instrument(skip_all)]
   async fn into_apub(self, context: &LemmyContext) -> Result<Page, LemmyError> {
     let creator_id = self.creator_id;
-    let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
+    let creator = Person::read(context.pool(), creator_id).await?;
     let community_id = self.community_id;
-    let community = blocking(context.pool(), move |conn| {
-      Community::read(conn, community_id)
-    })
-    .await??;
+    let community = Community::read(context.pool(), community_id).await?;
     let language = LanguageTag::new_single(self.language_id, context.pool()).await?;
 
     let page = Page {
@@ -146,7 +135,7 @@ impl ApubObject for ApubPost {
       verify_is_remote_object(page.id.inner(), context.settings())?;
     };
 
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
 
     let community = page.extract_community(context, request_counter).await?;
     check_apub_id_valid_with_strictness(
@@ -173,7 +162,7 @@ impl ApubObject for ApubPost {
   ) -> Result<ApubPost, LemmyError> {
     let creator = page
       .creator()?
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let community = page.extract_community(context, request_counter).await?;
 
@@ -199,7 +188,7 @@ impl ApubObject for ApubPost {
       let (embed_title, embed_description, embed_video_url) = metadata_res
         .map(|u| (u.title, u.description, u.embed_video_url))
         .unwrap_or_default();
-      let local_site = blocking(context.pool(), LocalSite::read).await?.ok();
+      let local_site = LocalSite::read(context.pool()).await.ok();
       let slur_regex = &local_site_opt_to_slur_regex(&local_site);
 
       let body_slurs_removed =
@@ -246,7 +235,7 @@ impl ApubObject for ApubPost {
       .dereference_local(context)
       .await;
 
-    let post = blocking(context.pool(), move |conn| Post::create(conn, &form)).await??;
+    let post = Post::create(context.pool(), &form).await?;
 
     // write mod log entries for sticky/lock
     if Page::is_stickied_changed(&old_post, &page.stickied) {
@@ -255,10 +244,7 @@ impl ApubObject for ApubPost {
         post_id: post.id,
         stickied: Some(post.stickied),
       };
-      blocking(context.pool(), move |conn| {
-        ModStickyPost::create(conn, &form)
-      })
-      .await??;
+      ModStickyPost::create(context.pool(), &form).await?;
     }
     if Page::is_locked_changed(&old_post, &page.comments_enabled) {
       let form = ModLockPostForm {
@@ -266,7 +252,7 @@ impl ApubObject for ApubPost {
         post_id: post.id,
         locked: Some(post.locked),
       };
-      blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
+      ModLockPost::create(context.pool(), &form).await?;
     }
 
     Ok(post.into())
@@ -291,8 +277,7 @@ mod tests {
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_post() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let (person, site) = parse_lemmy_person(&context).await;
     let community = parse_lemmy_community(&context).await;
 
@@ -314,9 +299,11 @@ mod tests {
     assert!(post.stickied);
     assert_eq!(request_counter, 0);
 
-    Post::delete(conn, post.id).unwrap();
-    Person::delete(conn, person.id).unwrap();
-    Community::delete(conn, community.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
+    Post::delete(context.pool(), post.id).await.unwrap();
+    Person::delete(context.pool(), person.id).await.unwrap();
+    Community::delete(context.pool(), community.id)
+      .await
+      .unwrap();
+    Site::delete(context.pool(), site.id).await.unwrap();
   }
 }
diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs
index 87f88de8..47a9c5d1 100644
--- a/crates/apub/src/objects/private_message.rs
+++ b/crates/apub/src/objects/private_message.rs
@@ -15,7 +15,7 @@ use activitypub_federation::{
   utils::verify_domains_match,
 };
 use chrono::NaiveDateTime;
-use lemmy_api_common::utils::{blocking, check_person_block};
+use lemmy_api_common::utils::check_person_block;
 use lemmy_db_schema::{
   source::{
     person::Person,
@@ -64,11 +64,9 @@ impl ApubObject for ApubPrivateMessage {
     context: &LemmyContext,
   ) -> Result<Option<Self>, LemmyError> {
     Ok(
-      blocking(context.pool(), move |conn| {
-        PrivateMessage::read_from_apub_id(conn, object_id)
-      })
-      .await??
-      .map(Into::into),
+      PrivateMessage::read_from_apub_id(context.pool(), object_id)
+        .await?
+        .map(Into::into),
     )
   }
 
@@ -80,11 +78,10 @@ impl ApubObject for ApubPrivateMessage {
   #[tracing::instrument(skip_all)]
   async fn into_apub(self, context: &LemmyContext) -> Result<ChatMessage, LemmyError> {
     let creator_id = self.creator_id;
-    let creator = blocking(context.pool(), move |conn| Person::read(conn, creator_id)).await??;
+    let creator = Person::read(context.pool(), creator_id).await?;
 
     let recipient_id = self.recipient_id;
-    let recipient =
-      blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
+    let recipient = Person::read(context.pool(), recipient_id).await?;
 
     let note = ChatMessage {
       r#type: ChatMessageType::ChatMessage,
@@ -110,7 +107,7 @@ impl ApubObject for ApubPrivateMessage {
     verify_domains_match(note.id.inner(), expected_domain)?;
     verify_domains_match(note.attributed_to.inner(), note.id.inner())?;
 
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
 
     check_apub_id_valid_with_strictness(
       note.id.inner(),
@@ -120,7 +117,7 @@ impl ApubObject for ApubPrivateMessage {
     )?;
     let person = note
       .attributed_to
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     if person.banned {
       return Err(LemmyError::from_message("Person is banned from site"));
@@ -136,10 +133,10 @@ impl ApubObject for ApubPrivateMessage {
   ) -> Result<ApubPrivateMessage, LemmyError> {
     let creator = note
       .attributed_to
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     let recipient = note.to[0]
-      .dereference(context, local_instance(context), request_counter)
+      .dereference(context, local_instance(context).await, request_counter)
       .await?;
     check_person_block(creator.id, recipient.id, context.pool()).await?;
 
@@ -154,10 +151,7 @@ impl ApubObject for ApubPrivateMessage {
       ap_id: Some(note.id.into()),
       local: Some(false),
     };
-    let pm = blocking(context.pool(), move |conn| {
-      PrivateMessage::create(conn, &form)
-    })
-    .await??;
+    let pm = PrivateMessage::create(context.pool(), &form).await?;
     Ok(pm.into())
   }
 }
@@ -200,18 +194,16 @@ mod tests {
     (person1, person2, site)
   }
 
-  fn cleanup(data: (ApubPerson, ApubPerson, ApubSite), context: &LemmyContext) {
-    let conn = &mut context.pool().get().unwrap();
-    Person::delete(conn, data.0.id).unwrap();
-    Person::delete(conn, data.1.id).unwrap();
-    Site::delete(conn, data.2.id).unwrap();
+  async fn cleanup(data: (ApubPerson, ApubPerson, ApubSite), context: &LemmyContext) {
+    Person::delete(context.pool(), data.0.id).await.unwrap();
+    Person::delete(context.pool(), data.1.id).await.unwrap();
+    Site::delete(context.pool(), data.2.id).await.unwrap();
   }
 
   #[actix_rt::test]
   #[serial]
   async fn test_parse_lemmy_pm() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let url = Url::parse("https://enterprise.lemmy.ml/private_message/1621").unwrap();
     let data = prepare_comment_test(&url, &context).await;
     let json: ChatMessage = file_to_json_object("assets/lemmy/objects/chat_message.json").unwrap();
@@ -231,15 +223,14 @@ mod tests {
     let to_apub = pm.into_apub(&context).await.unwrap();
     assert_json_include!(actual: json, expected: to_apub);
 
-    PrivateMessage::delete(conn, pm_id).unwrap();
-    cleanup(data, &context);
+    PrivateMessage::delete(context.pool(), pm_id).await.unwrap();
+    cleanup(data, &context).await;
   }
 
   #[actix_rt::test]
   #[serial]
   async fn test_parse_pleroma_pm() {
-    let context = init_context();
-    let conn = &mut context.pool().get().unwrap();
+    let context = init_context().await;
     let url = Url::parse("https://enterprise.lemmy.ml/private_message/1621").unwrap();
     let data = prepare_comment_test(&url, &context).await;
     let pleroma_url = Url::parse("https://queer.hacktivis.me/objects/2").unwrap();
@@ -256,7 +247,7 @@ mod tests {
     assert_eq!(pm.content.len(), 3);
     assert_eq!(request_counter, 0);
 
-    PrivateMessage::delete(conn, pm.id).unwrap();
-    cleanup(data, &context);
+    PrivateMessage::delete(context.pool(), pm.id).await.unwrap();
+    cleanup(data, &context).await;
   }
 }
diff --git a/crates/apub/src/protocol/collections/group_followers.rs b/crates/apub/src/protocol/collections/group_followers.rs
index eeea8e07..ac1ef228 100644
--- a/crates/apub/src/protocol/collections/group_followers.rs
+++ b/crates/apub/src/protocol/collections/group_followers.rs
@@ -1,6 +1,5 @@
 use crate::generate_followers_url;
 use activitystreams_kinds::collection::CollectionType;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::source::community::Community;
 use lemmy_db_views_actor::structs::CommunityFollowerView;
 use lemmy_utils::error::LemmyError;
@@ -23,10 +22,8 @@ impl GroupFollowers {
     context: &LemmyContext,
   ) -> Result<GroupFollowers, LemmyError> {
     let community_id = community.id;
-    let community_followers = blocking(context.pool(), move |conn| {
-      CommunityFollowerView::for_community(conn, community_id)
-    })
-    .await??;
+    let community_followers =
+      CommunityFollowerView::for_community(context.pool(), community_id).await?;
 
     Ok(GroupFollowers {
       id: generate_followers_url(&community.actor_id)?.into(),
diff --git a/crates/apub/src/protocol/mod.rs b/crates/apub/src/protocol/mod.rs
index c81a5c15..c259a6e9 100644
--- a/crates/apub/src/protocol/mod.rs
+++ b/crates/apub/src/protocol/mod.rs
@@ -74,7 +74,7 @@ impl<Kind: Id + DeserializeOwned> IdOrNestedObject<Kind> {
   ) -> Result<Kind, LemmyError> {
     match self {
       IdOrNestedObject::Id(i) => {
-        Ok(fetch_object_http(&i, local_instance(context), request_counter).await?)
+        Ok(fetch_object_http(&i, local_instance(context).await, request_counter).await?)
       }
       IdOrNestedObject::NestedObject(o) => Ok(o),
     }
diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs
index 7d207da4..1935589e 100644
--- a/crates/apub/src/protocol/objects/group.rs
+++ b/crates/apub/src/protocol/objects/group.rs
@@ -19,7 +19,7 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::actor::GroupType;
 use chrono::{DateTime, FixedOffset};
-use lemmy_api_common::utils::{blocking, local_site_opt_to_slur_regex};
+use lemmy_api_common::utils::local_site_opt_to_slur_regex;
 use lemmy_db_schema::{
   newtypes::InstanceId,
   source::community::{CommunityInsertForm, CommunityUpdateForm},
@@ -75,7 +75,7 @@ impl Group {
     expected_domain: &Url,
     context: &LemmyContext,
   ) -> Result<(), LemmyError> {
-    let local_site_data = blocking(context.pool(), fetch_local_site_data).await??;
+    let local_site_data = fetch_local_site_data(context.pool()).await?;
 
     check_apub_id_valid_with_strictness(
       self.id.inner(),
diff --git a/crates/apub/src/protocol/objects/mod.rs b/crates/apub/src/protocol/objects/mod.rs
index 31b8eb32..0fcbc08e 100644
--- a/crates/apub/src/protocol/objects/mod.rs
+++ b/crates/apub/src/protocol/objects/mod.rs
@@ -1,4 +1,3 @@
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{newtypes::LanguageId, source::language::Language, utils::DbPool};
 use lemmy_utils::error::LemmyError;
 use serde::{Deserialize, Serialize};
@@ -31,7 +30,7 @@ impl LanguageTag {
     lang: LanguageId,
     pool: &DbPool,
   ) -> Result<Option<LanguageTag>, LemmyError> {
-    let lang = blocking(pool, move |conn| Language::read_from_id(conn, lang)).await??;
+    let lang = Language::read_from_id(pool, lang).await?;
 
     // undetermined
     if lang.code == "und" {
@@ -45,16 +44,14 @@ impl LanguageTag {
   }
 
   pub(crate) async fn new_multiple(
-    langs: Vec<LanguageId>,
+    lang_ids: Vec<LanguageId>,
     pool: &DbPool,
   ) -> Result<Vec<LanguageTag>, LemmyError> {
-    let langs = blocking(pool, move |conn| {
-      langs
-        .into_iter()
-        .map(|l| Language::read_from_id(conn, l))
-        .collect::<Result<Vec<Language>, diesel::result::Error>>()
-    })
-    .await??;
+    let mut langs = Vec::<Language>::new();
+
+    for l in lang_ids {
+      langs.push(Language::read_from_id(pool, l).await?);
+    }
 
     let langs = langs
       .into_iter()
@@ -71,10 +68,7 @@ impl LanguageTag {
     pool: &DbPool,
   ) -> Result<Option<LanguageId>, LemmyError> {
     let identifier = lang.map(|l| l.identifier);
-    let language = blocking(pool, move |conn| {
-      Language::read_id_from_code_opt(conn, identifier.as_deref())
-    })
-    .await??;
+    let language = Language::read_id_from_code_opt(pool, identifier.as_deref()).await?;
 
     Ok(language)
   }
@@ -83,15 +77,14 @@ impl LanguageTag {
     langs: Vec<Self>,
     pool: &DbPool,
   ) -> Result<Vec<LanguageId>, LemmyError> {
-    let languages = blocking(pool, move |conn| {
-      langs
-        .into_iter()
-        .map(|l| l.identifier)
-        .map(|l| Language::read_id_from_code(conn, &l))
-        .collect::<Result<Vec<LanguageId>, diesel::result::Error>>()
-    })
-    .await??;
-    Ok(languages)
+    let mut language_ids = Vec::new();
+
+    for l in langs {
+      let id = l.identifier;
+      language_ids.push(Language::read_id_from_code(pool, &id).await?);
+    }
+
+    Ok(language_ids)
   }
 }
 
diff --git a/crates/apub/src/protocol/objects/note.rs b/crates/apub/src/protocol/objects/note.rs
index cdcec1a7..c91ed8d1 100644
--- a/crates/apub/src/protocol/objects/note.rs
+++ b/crates/apub/src/protocol/objects/note.rs
@@ -14,7 +14,6 @@ use activitypub_federation::{
 };
 use activitystreams_kinds::object::NoteType;
 use chrono::{DateTime, FixedOffset};
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{source::post::Post, traits::Crud};
 use lemmy_utils::error::LemmyError;
 use lemmy_websocket::LemmyContext;
@@ -59,7 +58,7 @@ impl Note {
     let parent = Box::pin(
       self
         .in_reply_to
-        .dereference(context, local_instance(context), request_counter)
+        .dereference(context, local_instance(context).await, request_counter)
         .await?,
     );
     match parent.deref() {
@@ -69,7 +68,7 @@ impl Note {
       }
       PostOrComment::Comment(c) => {
         let post_id = c.post_id;
-        let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
+        let post = Post::read(context.pool(), post_id).await?;
         let comment = c.deref().to_owned();
         Ok((post.into(), Some(comment)))
       }
diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs
index 1cf55aca..5ffb4869 100644
--- a/crates/apub/src/protocol/objects/page.rs
+++ b/crates/apub/src/protocol/objects/page.rs
@@ -155,7 +155,7 @@ impl Page {
           if let Some(cid) = iter.next() {
             let cid = ObjectId::new(cid.clone());
             if let Ok(c) = cid
-              .dereference(context, local_instance(context), request_counter)
+              .dereference(context, local_instance(context).await, request_counter)
               .await
             {
               break Ok(c);
@@ -170,7 +170,7 @@ impl Page {
           .find(|a| a.kind == PersonOrGroupType::Group)
           .map(|a| ObjectId::<ApubCommunity>::new(a.id.clone().into_inner()))
           .ok_or_else(|| LemmyError::from_message("page does not specify group"))?
-          .dereference(context, local_instance(context), request_counter)
+          .dereference(context, local_instance(context).await, request_counter)
           .await
       }
     }
diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml
index 5808f81c..da508b29 100644
--- a/crates/db_schema/Cargo.toml
+++ b/crates/db_schema/Cargo.toml
@@ -19,22 +19,26 @@ full = ["diesel", "diesel-derive-newtype", "diesel_migrations", "bcrypt", "lemmy
 
 [dependencies]
 chrono = { version = "0.4.22", features = ["serde"], default-features = false }
-serde = { version = "1.0.145", features = ["derive"] }
+serde = { version = "1.0.147", features = ["derive"] }
 url = { version = "2.3.1", features = ["serde"] }
 strum = "0.24.1"
 strum_macros = "0.24.3"
-serde_json = { version = "1.0.85", features = ["preserve_order"], optional = true }
+serde_json = { version = "1.0.87", features = ["preserve_order"], optional = true }
 activitypub_federation = { version = "0.2.3", optional = true }
 lemmy_utils = { version = "=0.16.5", path = "../utils", optional = true }
 bcrypt = { version = "0.13.0", optional = true }
-diesel = { version = "2.0.0", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
+diesel = { version = "2.0.2", features = ["postgres","chrono", "serde_json"], optional = true }
 diesel-derive-newtype = { version = "2.0.0-rc.0", optional = true }
 diesel_migrations = { version = "2.0.0", optional = true }
+diesel-async = { version = "0.1.1", features = ["postgres", "bb8"] }
+bb8 = "0.8.0"
 sha2 = { version = "0.10.6", optional = true }
 regex = { version = "1.6.0", optional = true }
 once_cell = { version = "1.15.0", optional = true }
 diesel_ltree = "0.3.0"
 typed-builder = "0.10.0"
+async-trait = "0.1.58"
+tokio = "1.21.2"
 
 [dev-dependencies]
 serial_test = "0.9.0"
diff --git a/crates/db_schema/src/aggregates/comment_aggregates.rs b/crates/db_schema/src/aggregates/comment_aggregates.rs
index 1130d910..56528a5f 100644
--- a/crates/db_schema/src/aggregates/comment_aggregates.rs
+++ b/crates/db_schema/src/aggregates/comment_aggregates.rs
@@ -2,14 +2,18 @@ use crate::{
   aggregates::structs::CommentAggregates,
   newtypes::CommentId,
   schema::comment_aggregates,
+  utils::{get_conn, DbPool},
 };
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl CommentAggregates {
-  pub fn read(conn: &mut PgConnection, comment_id: CommentId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, comment_id: CommentId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     comment_aggregates::table
       .filter(comment_aggregates::comment_id.eq(comment_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -25,16 +29,16 @@ mod tests {
       post::{Post, PostInsertForm},
     },
     traits::{Crud, Likeable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy_comment_agg".into())
@@ -42,7 +46,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let another_person = PersonInsertForm::builder()
       .name("jerry_comment_agg".into())
@@ -50,7 +54,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let another_inserted_person = Person::create(conn, &another_person).unwrap();
+    let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL_comment_agg".into())
@@ -59,7 +63,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -67,7 +71,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -75,7 +79,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let child_comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -84,7 +88,9 @@ mod tests {
       .build();
 
     let _inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
     let comment_like = CommentLikeForm {
       comment_id: inserted_comment.id,
@@ -93,9 +99,11 @@ mod tests {
       score: 1,
     };
 
-    CommentLike::like(conn, &comment_like).unwrap();
+    CommentLike::like(pool, &comment_like).await.unwrap();
 
-    let comment_aggs_before_delete = CommentAggregates::read(conn, inserted_comment.id).unwrap();
+    let comment_aggs_before_delete = CommentAggregates::read(pool, inserted_comment.id)
+      .await
+      .unwrap();
 
     assert_eq!(1, comment_aggs_before_delete.score);
     assert_eq!(1, comment_aggs_before_delete.upvotes);
@@ -109,37 +117,47 @@ mod tests {
       score: -1,
     };
 
-    CommentLike::like(conn, &comment_dislike).unwrap();
+    CommentLike::like(pool, &comment_dislike).await.unwrap();
 
-    let comment_aggs_after_dislike = CommentAggregates::read(conn, inserted_comment.id).unwrap();
+    let comment_aggs_after_dislike = CommentAggregates::read(pool, inserted_comment.id)
+      .await
+      .unwrap();
 
     assert_eq!(0, comment_aggs_after_dislike.score);
     assert_eq!(1, comment_aggs_after_dislike.upvotes);
     assert_eq!(1, comment_aggs_after_dislike.downvotes);
 
     // Remove the first comment like
-    CommentLike::remove(conn, inserted_person.id, inserted_comment.id).unwrap();
-    let after_like_remove = CommentAggregates::read(conn, inserted_comment.id).unwrap();
+    CommentLike::remove(pool, inserted_person.id, inserted_comment.id)
+      .await
+      .unwrap();
+    let after_like_remove = CommentAggregates::read(pool, inserted_comment.id)
+      .await
+      .unwrap();
     assert_eq!(-1, after_like_remove.score);
     assert_eq!(0, after_like_remove.upvotes);
     assert_eq!(1, after_like_remove.downvotes);
 
     // Remove the parent post
-    Post::delete(conn, inserted_post.id).unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
 
     // Should be none found, since the post was deleted
-    let after_delete = CommentAggregates::read(conn, inserted_comment.id);
+    let after_delete = CommentAggregates::read(pool, inserted_comment.id).await;
     assert!(after_delete.is_err());
 
     // This should delete all the associated rows, and fire triggers
-    Person::delete(conn, another_inserted_person.id).unwrap();
-    let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    Person::delete(pool, another_inserted_person.id)
+      .await
+      .unwrap();
+    let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, person_num_deleted);
 
     // Delete the community
-    let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
+    let community_num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, community_num_deleted);
 
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/aggregates/community_aggregates.rs b/crates/db_schema/src/aggregates/community_aggregates.rs
index 1a2c4d24..96dbb8fb 100644
--- a/crates/db_schema/src/aggregates/community_aggregates.rs
+++ b/crates/db_schema/src/aggregates/community_aggregates.rs
@@ -2,14 +2,18 @@ use crate::{
   aggregates::structs::CommunityAggregates,
   newtypes::CommunityId,
   schema::community_aggregates,
+  utils::{get_conn, DbPool},
 };
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl CommunityAggregates {
-  pub fn read(conn: &mut PgConnection, community_id: CommunityId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, community_id: CommunityId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     community_aggregates::table
       .filter(community_aggregates::community_id.eq(community_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -25,16 +29,16 @@ mod tests {
       post::{Post, PostInsertForm},
     },
     traits::{Crud, Followable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy_community_agg".into())
@@ -42,7 +46,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let another_person = PersonInsertForm::builder()
       .name("jerry_community_agg".into())
@@ -50,7 +54,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let another_inserted_person = Person::create(conn, &another_person).unwrap();
+    let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL_community_agg".into())
@@ -59,7 +63,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let another_community = CommunityInsertForm::builder()
       .name("TIL_community_agg_2".into())
@@ -68,7 +72,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let another_inserted_community = Community::create(conn, &another_community).unwrap();
+    let another_inserted_community = Community::create(pool, &another_community).await.unwrap();
 
     let first_person_follow = CommunityFollowerForm {
       community_id: inserted_community.id,
@@ -76,7 +80,9 @@ mod tests {
       pending: false,
     };
 
-    CommunityFollower::follow(conn, &first_person_follow).unwrap();
+    CommunityFollower::follow(pool, &first_person_follow)
+      .await
+      .unwrap();
 
     let second_person_follow = CommunityFollowerForm {
       community_id: inserted_community.id,
@@ -84,7 +90,9 @@ mod tests {
       pending: false,
     };
 
-    CommunityFollower::follow(conn, &second_person_follow).unwrap();
+    CommunityFollower::follow(pool, &second_person_follow)
+      .await
+      .unwrap();
 
     let another_community_follow = CommunityFollowerForm {
       community_id: another_inserted_community.id,
@@ -92,7 +100,9 @@ mod tests {
       pending: false,
     };
 
-    CommunityFollower::follow(conn, &another_community_follow).unwrap();
+    CommunityFollower::follow(pool, &another_community_follow)
+      .await
+      .unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -100,7 +110,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -108,7 +118,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let child_comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -117,57 +127,78 @@ mod tests {
       .build();
 
     let _inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
-    let community_aggregates_before_delete =
-      CommunityAggregates::read(conn, inserted_community.id).unwrap();
+    let community_aggregates_before_delete = CommunityAggregates::read(pool, inserted_community.id)
+      .await
+      .unwrap();
 
     assert_eq!(2, community_aggregates_before_delete.subscribers);
     assert_eq!(1, community_aggregates_before_delete.posts);
     assert_eq!(2, community_aggregates_before_delete.comments);
 
     // Test the other community
-    let another_community_aggs =
-      CommunityAggregates::read(conn, another_inserted_community.id).unwrap();
+    let another_community_aggs = CommunityAggregates::read(pool, another_inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, another_community_aggs.subscribers);
     assert_eq!(0, another_community_aggs.posts);
     assert_eq!(0, another_community_aggs.comments);
 
     // Unfollow test
-    CommunityFollower::unfollow(conn, &second_person_follow).unwrap();
-    let after_unfollow = CommunityAggregates::read(conn, inserted_community.id).unwrap();
+    CommunityFollower::unfollow(pool, &second_person_follow)
+      .await
+      .unwrap();
+    let after_unfollow = CommunityAggregates::read(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, after_unfollow.subscribers);
 
     // Follow again just for the later tests
-    CommunityFollower::follow(conn, &second_person_follow).unwrap();
-    let after_follow_again = CommunityAggregates::read(conn, inserted_community.id).unwrap();
+    CommunityFollower::follow(pool, &second_person_follow)
+      .await
+      .unwrap();
+    let after_follow_again = CommunityAggregates::read(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(2, after_follow_again.subscribers);
 
     // Remove a parent comment (the comment count should also be 0)
-    Post::delete(conn, inserted_post.id).unwrap();
-    let after_parent_post_delete = CommunityAggregates::read(conn, inserted_community.id).unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    let after_parent_post_delete = CommunityAggregates::read(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(0, after_parent_post_delete.comments);
     assert_eq!(0, after_parent_post_delete.posts);
 
     // Remove the 2nd person
-    Person::delete(conn, another_inserted_person.id).unwrap();
-    let after_person_delete = CommunityAggregates::read(conn, inserted_community.id).unwrap();
+    Person::delete(pool, another_inserted_person.id)
+      .await
+      .unwrap();
+    let after_person_delete = CommunityAggregates::read(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, after_person_delete.subscribers);
 
     // This should delete all the associated rows, and fire triggers
-    let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, person_num_deleted);
 
     // Delete the community
-    let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
+    let community_num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, community_num_deleted);
 
-    let another_community_num_deleted =
-      Community::delete(conn, another_inserted_community.id).unwrap();
+    let another_community_num_deleted = Community::delete(pool, another_inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, another_community_num_deleted);
 
     // Should be none found, since the creator was deleted
-    let after_delete = CommunityAggregates::read(conn, inserted_community.id);
+    let after_delete = CommunityAggregates::read(pool, inserted_community.id).await;
     assert!(after_delete.is_err());
   }
 }
diff --git a/crates/db_schema/src/aggregates/person_aggregates.rs b/crates/db_schema/src/aggregates/person_aggregates.rs
index e9417efb..b8e1887a 100644
--- a/crates/db_schema/src/aggregates/person_aggregates.rs
+++ b/crates/db_schema/src/aggregates/person_aggregates.rs
@@ -1,11 +1,19 @@
-use crate::{aggregates::structs::PersonAggregates, newtypes::PersonId, schema::person_aggregates};
-use diesel::{result::Error, *};
+use crate::{
+  aggregates::structs::PersonAggregates,
+  newtypes::PersonId,
+  schema::person_aggregates,
+  utils::{get_conn, DbPool},
+};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl PersonAggregates {
-  pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     person_aggregates::table
       .filter(person_aggregates::person_id.eq(person_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -21,16 +29,16 @@ mod tests {
       post::{Post, PostInsertForm, PostLike, PostLikeForm},
     },
     traits::{Crud, Likeable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy_user_agg".into())
@@ -38,7 +46,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let another_person = PersonInsertForm::builder()
       .name("jerry_user_agg".into())
@@ -46,7 +54,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let another_inserted_person = Person::create(conn, &another_person).unwrap();
+    let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL_site_agg".into())
@@ -55,7 +63,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -63,7 +71,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let post_like = PostLikeForm {
       post_id: inserted_post.id,
@@ -71,7 +79,7 @@ mod tests {
       score: 1,
     };
 
-    let _inserted_post_like = PostLike::like(conn, &post_like).unwrap();
+    let _inserted_post_like = PostLike::like(pool, &post_like).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -79,7 +87,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let mut comment_like = CommentLikeForm {
       comment_id: inserted_comment.id,
@@ -88,7 +96,7 @@ mod tests {
       score: 1,
     };
 
-    let _inserted_comment_like = CommentLike::like(conn, &comment_like).unwrap();
+    let _inserted_comment_like = CommentLike::like(pool, &comment_like).await.unwrap();
 
     let child_comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -97,7 +105,9 @@ mod tests {
       .build();
 
     let inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
     let child_comment_like = CommentLikeForm {
       comment_id: inserted_child_comment.id,
@@ -106,9 +116,11 @@ mod tests {
       score: 1,
     };
 
-    let _inserted_child_comment_like = CommentLike::like(conn, &child_comment_like).unwrap();
+    let _inserted_child_comment_like = CommentLike::like(pool, &child_comment_like).await.unwrap();
 
-    let person_aggregates_before_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
+    let person_aggregates_before_delete = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
 
     assert_eq!(1, person_aggregates_before_delete.post_count);
     assert_eq!(1, person_aggregates_before_delete.post_score);
@@ -116,47 +128,65 @@ mod tests {
     assert_eq!(2, person_aggregates_before_delete.comment_score);
 
     // Remove a post like
-    PostLike::remove(conn, inserted_person.id, inserted_post.id).unwrap();
-    let after_post_like_remove = PersonAggregates::read(conn, inserted_person.id).unwrap();
+    PostLike::remove(pool, inserted_person.id, inserted_post.id)
+      .await
+      .unwrap();
+    let after_post_like_remove = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
     assert_eq!(0, after_post_like_remove.post_score);
 
     // Remove a parent comment (the scores should also be removed)
-    Comment::delete(conn, inserted_comment.id).unwrap();
-    Comment::delete(conn, inserted_child_comment.id).unwrap();
-    let after_parent_comment_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
+    Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Comment::delete(pool, inserted_child_comment.id)
+      .await
+      .unwrap();
+    let after_parent_comment_delete = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
     assert_eq!(0, after_parent_comment_delete.comment_count);
     assert_eq!(0, after_parent_comment_delete.comment_score);
 
     // Add in the two comments again, then delete the post.
-    let new_parent_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let new_parent_comment = Comment::create(pool, &comment_form, None).await.unwrap();
     let _new_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&new_parent_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&new_parent_comment.path))
+        .await
+        .unwrap();
     comment_like.comment_id = new_parent_comment.id;
-    CommentLike::like(conn, &comment_like).unwrap();
-    let after_comment_add = PersonAggregates::read(conn, inserted_person.id).unwrap();
+    CommentLike::like(pool, &comment_like).await.unwrap();
+    let after_comment_add = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
     assert_eq!(2, after_comment_add.comment_count);
     assert_eq!(1, after_comment_add.comment_score);
 
-    Post::delete(conn, inserted_post.id).unwrap();
-    let after_post_delete = PersonAggregates::read(conn, inserted_person.id).unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    let after_post_delete = PersonAggregates::read(pool, inserted_person.id)
+      .await
+      .unwrap();
     assert_eq!(0, after_post_delete.comment_score);
     assert_eq!(0, after_post_delete.comment_count);
     assert_eq!(0, after_post_delete.post_score);
     assert_eq!(0, after_post_delete.post_count);
 
     // This should delete all the associated rows, and fire triggers
-    let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, person_num_deleted);
-    Person::delete(conn, another_inserted_person.id).unwrap();
+    Person::delete(pool, another_inserted_person.id)
+      .await
+      .unwrap();
 
     // Delete the community
-    let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
+    let community_num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, community_num_deleted);
 
     // Should be none found
-    let after_delete = PersonAggregates::read(conn, inserted_person.id);
+    let after_delete = PersonAggregates::read(pool, inserted_person.id).await;
     assert!(after_delete.is_err());
 
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/aggregates/person_post_aggregates.rs b/crates/db_schema/src/aggregates/person_post_aggregates.rs
index 2d268d4f..5a2fb17d 100644
--- a/crates/db_schema/src/aggregates/person_post_aggregates.rs
+++ b/crates/db_schema/src/aggregates/person_post_aggregates.rs
@@ -1,27 +1,29 @@
 use crate::{
   aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
+  diesel::BoolExpressionMethods,
   newtypes::{PersonId, PostId},
+  schema::person_post_aggregates::dsl::*,
+  utils::{get_conn, DbPool},
 };
-use diesel::{result::Error, *};
+use diesel::{insert_into, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl PersonPostAggregates {
-  pub fn upsert(conn: &mut PgConnection, form: &PersonPostAggregatesForm) -> Result<Self, Error> {
-    use crate::schema::person_post_aggregates::dsl::*;
+  pub async fn upsert(pool: &DbPool, form: &PersonPostAggregatesForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(person_post_aggregates)
       .values(form)
       .on_conflict((person_id, post_id))
       .do_update()
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
-  pub fn read(
-    conn: &mut PgConnection,
-    person_id_: PersonId,
-    post_id_: PostId,
-  ) -> Result<Self, Error> {
-    use crate::schema::person_post_aggregates::dsl::*;
+  pub async fn read(pool: &DbPool, person_id_: PersonId, post_id_: PostId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     person_post_aggregates
       .filter(post_id.eq(post_id_).and(person_id.eq(person_id_)))
       .first::<Self>(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/aggregates/post_aggregates.rs b/crates/db_schema/src/aggregates/post_aggregates.rs
index ac7c0eac..dca5fb82 100644
--- a/crates/db_schema/src/aggregates/post_aggregates.rs
+++ b/crates/db_schema/src/aggregates/post_aggregates.rs
@@ -1,11 +1,19 @@
-use crate::{aggregates::structs::PostAggregates, newtypes::PostId, schema::post_aggregates};
-use diesel::{result::Error, *};
+use crate::{
+  aggregates::structs::PostAggregates,
+  newtypes::PostId,
+  schema::post_aggregates,
+  utils::{get_conn, DbPool},
+};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl PostAggregates {
-  pub fn read(conn: &mut PgConnection, post_id: PostId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, post_id: PostId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     post_aggregates::table
       .filter(post_aggregates::post_id.eq(post_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -21,16 +29,16 @@ mod tests {
       post::{Post, PostInsertForm, PostLike, PostLikeForm},
     },
     traits::{Crud, Likeable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy_community_agg".into())
@@ -38,7 +46,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let another_person = PersonInsertForm::builder()
       .name("jerry_community_agg".into())
@@ -46,7 +54,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let another_inserted_person = Person::create(conn, &another_person).unwrap();
+    let another_inserted_person = Person::create(pool, &another_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL_community_agg".into())
@@ -55,7 +63,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -63,7 +71,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -71,7 +79,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let child_comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -80,7 +88,9 @@ mod tests {
       .build();
 
     let inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
     let post_like = PostLikeForm {
       post_id: inserted_post.id,
@@ -88,9 +98,9 @@ mod tests {
       score: 1,
     };
 
-    PostLike::like(conn, &post_like).unwrap();
+    PostLike::like(pool, &post_like).await.unwrap();
 
-    let post_aggs_before_delete = PostAggregates::read(conn, inserted_post.id).unwrap();
+    let post_aggs_before_delete = PostAggregates::read(pool, inserted_post.id).await.unwrap();
 
     assert_eq!(2, post_aggs_before_delete.comments);
     assert_eq!(1, post_aggs_before_delete.score);
@@ -104,9 +114,9 @@ mod tests {
       score: -1,
     };
 
-    PostLike::like(conn, &post_dislike).unwrap();
+    PostLike::like(pool, &post_dislike).await.unwrap();
 
-    let post_aggs_after_dislike = PostAggregates::read(conn, inserted_post.id).unwrap();
+    let post_aggs_after_dislike = PostAggregates::read(pool, inserted_post.id).await.unwrap();
 
     assert_eq!(2, post_aggs_after_dislike.comments);
     assert_eq!(0, post_aggs_after_dislike.score);
@@ -114,35 +124,43 @@ mod tests {
     assert_eq!(1, post_aggs_after_dislike.downvotes);
 
     // Remove the comments
-    Comment::delete(conn, inserted_comment.id).unwrap();
-    Comment::delete(conn, inserted_child_comment.id).unwrap();
-    let after_comment_delete = PostAggregates::read(conn, inserted_post.id).unwrap();
+    Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Comment::delete(pool, inserted_child_comment.id)
+      .await
+      .unwrap();
+    let after_comment_delete = PostAggregates::read(pool, inserted_post.id).await.unwrap();
     assert_eq!(0, after_comment_delete.comments);
     assert_eq!(0, after_comment_delete.score);
     assert_eq!(1, after_comment_delete.upvotes);
     assert_eq!(1, after_comment_delete.downvotes);
 
     // Remove the first post like
-    PostLike::remove(conn, inserted_person.id, inserted_post.id).unwrap();
-    let after_like_remove = PostAggregates::read(conn, inserted_post.id).unwrap();
+    PostLike::remove(pool, inserted_person.id, inserted_post.id)
+      .await
+      .unwrap();
+    let after_like_remove = PostAggregates::read(pool, inserted_post.id).await.unwrap();
     assert_eq!(0, after_like_remove.comments);
     assert_eq!(-1, after_like_remove.score);
     assert_eq!(0, after_like_remove.upvotes);
     assert_eq!(1, after_like_remove.downvotes);
 
     // This should delete all the associated rows, and fire triggers
-    Person::delete(conn, another_inserted_person.id).unwrap();
-    let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    Person::delete(pool, another_inserted_person.id)
+      .await
+      .unwrap();
+    let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, person_num_deleted);
 
     // Delete the community
-    let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
+    let community_num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, community_num_deleted);
 
     // Should be none found, since the creator was deleted
-    let after_delete = PostAggregates::read(conn, inserted_post.id);
+    let after_delete = PostAggregates::read(pool, inserted_post.id).await;
     assert!(after_delete.is_err());
 
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/aggregates/site_aggregates.rs b/crates/db_schema/src/aggregates/site_aggregates.rs
index 41e82c95..8b4ccb37 100644
--- a/crates/db_schema/src/aggregates/site_aggregates.rs
+++ b/crates/db_schema/src/aggregates/site_aggregates.rs
@@ -1,9 +1,15 @@
-use crate::{aggregates::structs::SiteAggregates, schema::site_aggregates};
-use diesel::{result::Error, *};
+use crate::{
+  aggregates::structs::SiteAggregates,
+  schema::site_aggregates,
+  utils::{get_conn, DbPool},
+};
+use diesel::result::Error;
+use diesel_async::RunQueryDsl;
 
 impl SiteAggregates {
-  pub fn read(conn: &mut PgConnection) -> Result<Self, Error> {
-    site_aggregates::table.first::<Self>(conn)
+  pub async fn read(pool: &DbPool) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    site_aggregates::table.first::<Self>(conn).await
   }
 }
 
@@ -20,16 +26,16 @@ mod tests {
       site::{Site, SiteInsertForm},
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy_site_agg".into())
@@ -37,14 +43,14 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let site_form = SiteInsertForm::builder()
       .name("test_site".into())
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_site = Site::create(conn, &site_form).unwrap();
+    let inserted_site = Site::create(pool, &site_form).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL_site_agg".into())
@@ -53,7 +59,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -62,8 +68,8 @@ mod tests {
       .build();
 
     // Insert two of those posts
-    let inserted_post = Post::create(conn, &new_post).unwrap();
-    let _inserted_post_again = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
+    let _inserted_post_again = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -72,7 +78,7 @@ mod tests {
       .build();
 
     // Insert two of those comments
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let child_comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -81,9 +87,11 @@ mod tests {
       .build();
 
     let _inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
-    let site_aggregates_before_delete = SiteAggregates::read(conn).unwrap();
+    let site_aggregates_before_delete = SiteAggregates::read(pool).await.unwrap();
 
     // TODO: this is unstable, sometimes it returns 0 users, sometimes 1
     //assert_eq!(0, site_aggregates_before_delete.users);
@@ -92,27 +100,29 @@ mod tests {
     assert_eq!(2, site_aggregates_before_delete.comments);
 
     // Try a post delete
-    Post::delete(conn, inserted_post.id).unwrap();
-    let site_aggregates_after_post_delete = SiteAggregates::read(conn).unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    let site_aggregates_after_post_delete = SiteAggregates::read(pool).await.unwrap();
     assert_eq!(1, site_aggregates_after_post_delete.posts);
     assert_eq!(0, site_aggregates_after_post_delete.comments);
 
     // This shouuld delete all the associated rows, and fire triggers
-    let person_num_deleted = Person::delete(conn, inserted_person.id).unwrap();
+    let person_num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
     assert_eq!(1, person_num_deleted);
 
     // Delete the community
-    let community_num_deleted = Community::delete(conn, inserted_community.id).unwrap();
+    let community_num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
     assert_eq!(1, community_num_deleted);
 
     // Site should still exist, it can without a site creator.
-    let after_delete_creator = SiteAggregates::read(conn);
+    let after_delete_creator = SiteAggregates::read(pool).await;
     assert!(after_delete_creator.is_ok());
 
-    Site::delete(conn, inserted_site.id).unwrap();
-    let after_delete_site = SiteAggregates::read(conn);
+    Site::delete(pool, inserted_site.id).await.unwrap();
+    let after_delete_site = SiteAggregates::read(pool).await;
     assert!(after_delete_site.is_err());
 
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/aggregates/structs.rs b/crates/db_schema/src/aggregates/structs.rs
index 0cc4dd05..08d5e914 100644
--- a/crates/db_schema/src/aggregates/structs.rs
+++ b/crates/db_schema/src/aggregates/structs.rs
@@ -1,4 +1,4 @@
-use crate::newtypes::{CommentId, CommunityId, PersonId, PostId};
+use crate::newtypes::{CommentId, CommunityId, PersonId, PostId, SiteId};
 #[cfg(feature = "full")]
 use crate::schema::{
   comment_aggregates,
@@ -102,7 +102,7 @@ pub struct PersonPostAggregatesForm {
 #[cfg_attr(feature = "full", diesel(belongs_to(crate::source::site::Site)))]
 pub struct SiteAggregates {
   pub id: i32,
-  pub site_id: i32,
+  pub site_id: SiteId,
   pub users: i64,
   pub posts: i64,
   pub comments: i64,
diff --git a/crates/db_schema/src/impls/activity.rs b/crates/db_schema/src/impls/activity.rs
index c24a66bd..0809ee9c 100644
--- a/crates/db_schema/src/impls/activity.rs
+++ b/crates/db_schema/src/impls/activity.rs
@@ -1,61 +1,74 @@
-use crate::{newtypes::DbUrl, source::activity::*, traits::Crud};
+use crate::{
+  newtypes::DbUrl,
+  schema::activity::dsl::*,
+  source::activity::*,
+  traits::Crud,
+  utils::{get_conn, DbPool},
+};
 use diesel::{
   dsl::*,
   result::{DatabaseErrorKind, Error},
-  *,
+  ExpressionMethods,
+  QueryDsl,
 };
+use diesel_async::RunQueryDsl;
 use serde_json::Value;
 
+#[async_trait]
 impl Crud for Activity {
   type InsertForm = ActivityInsertForm;
   type UpdateForm = ActivityUpdateForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, activity_id: i32) -> Result<Self, Error> {
-    use crate::schema::activity::dsl::*;
-    activity.find(activity_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, activity_id: i32) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    activity.find(activity_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, new_activity: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::activity::dsl::*;
+  async fn create(pool: &DbPool, new_activity: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(activity)
       .values(new_activity)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     activity_id: i32,
     new_activity: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::activity::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(activity.find(activity_id))
       .set(new_activity)
       .get_result::<Self>(conn)
+      .await
   }
-  fn delete(conn: &mut PgConnection, activity_id: i32) -> Result<usize, Error> {
-    use crate::schema::activity::dsl::*;
-    diesel::delete(activity.find(activity_id)).execute(conn)
+  async fn delete(pool: &DbPool, activity_id: i32) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(activity.find(activity_id))
+      .execute(conn)
+      .await
   }
 }
 
 impl Activity {
   /// Returns true if the insert was successful
   // TODO this should probably just be changed to an upsert on_conflict, rather than an error
-  pub fn insert(
-    conn: &mut PgConnection,
-    ap_id: DbUrl,
-    data: Value,
-    local: bool,
-    sensitive: Option<bool>,
+  pub async fn insert(
+    pool: &DbPool,
+    ap_id_: DbUrl,
+    data_: Value,
+    local_: bool,
+    sensitive_: Option<bool>,
   ) -> Result<bool, Error> {
     let activity_form = ActivityInsertForm {
-      ap_id,
-      data,
-      local: Some(local),
-      sensitive,
+      ap_id: ap_id_,
+      data: data_,
+      local: Some(local_),
+      sensitive: sensitive_,
       updated: None,
     };
-    match Activity::create(conn, &activity_form) {
+    match Activity::create(pool, &activity_form).await {
       Ok(_) => Ok(true),
       Err(e) => {
         if let Error::DatabaseError(DatabaseErrorKind::UniqueViolation, _) = e {
@@ -66,14 +79,12 @@ impl Activity {
     }
   }
 
-  pub fn read_from_apub_id(conn: &mut PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
-    use crate::schema::activity::dsl::*;
-    activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
-  }
-
-  pub fn delete_olds(conn: &mut PgConnection) -> Result<usize, Error> {
-    use crate::schema::activity::dsl::*;
-    diesel::delete(activity.filter(published.lt(now - 6.months()))).execute(conn)
+  pub async fn read_from_apub_id(pool: &DbPool, object_id: &DbUrl) -> Result<Activity, Error> {
+    let conn = &mut get_conn(pool).await?;
+    activity
+      .filter(ap_id.eq(object_id))
+      .first::<Self>(conn)
+      .await
   }
 }
 
@@ -87,18 +98,18 @@ mod tests {
       instance::Instance,
       person::{Person, PersonInsertForm},
     },
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serde_json::Value;
   use serial_test::serial;
   use url::Url;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let creator_form = PersonInsertForm::builder()
       .name("activity_creator_ pm".into())
@@ -106,9 +117,9 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_creator = Person::create(conn, &creator_form).unwrap();
+    let inserted_creator = Person::create(pool, &creator_form).await.unwrap();
 
-    let ap_id: DbUrl = Url::parse(
+    let ap_id_: DbUrl = Url::parse(
       "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
     )
     .unwrap()
@@ -128,17 +139,17 @@ mod tests {
     )
     .unwrap();
     let activity_form = ActivityInsertForm {
-      ap_id: ap_id.clone(),
+      ap_id: ap_id_.clone(),
       data: test_json.to_owned(),
       local: Some(true),
       sensitive: Some(false),
       updated: None,
     };
 
-    let inserted_activity = Activity::create(conn, &activity_form).unwrap();
+    let inserted_activity = Activity::create(pool, &activity_form).await.unwrap();
 
     let expected_activity = Activity {
-      ap_id: ap_id.clone(),
+      ap_id: ap_id_.clone(),
       id: inserted_activity.id,
       data: test_json,
       local: true,
@@ -147,10 +158,10 @@ mod tests {
       updated: None,
     };
 
-    let read_activity = Activity::read(conn, inserted_activity.id).unwrap();
-    let read_activity_by_apub_id = Activity::read_from_apub_id(conn, &ap_id).unwrap();
-    Person::delete(conn, inserted_creator.id).unwrap();
-    Activity::delete(conn, inserted_activity.id).unwrap();
+    let read_activity = Activity::read(pool, inserted_activity.id).await.unwrap();
+    let read_activity_by_apub_id = Activity::read_from_apub_id(pool, &ap_id_).await.unwrap();
+    Person::delete(pool, inserted_creator.id).await.unwrap();
+    Activity::delete(pool, inserted_activity.id).await.unwrap();
 
     assert_eq!(expected_activity, read_activity);
     assert_eq!(expected_activity, read_activity_by_apub_id);
diff --git a/crates/db_schema/src/impls/actor_language.rs b/crates/db_schema/src/impls/actor_language.rs
index 6525a82d..4b8f3e37 100644
--- a/crates/db_schema/src/impls/actor_language.rs
+++ b/crates/db_schema/src/impls/actor_language.rs
@@ -1,126 +1,157 @@
 use crate::{
   diesel::JoinOnDsl,
   newtypes::{CommunityId, InstanceId, LanguageId, LocalUserId, SiteId},
+  schema::{local_site, site, site_language},
   source::{actor_language::*, language::Language, site::Site},
+  utils::{get_conn, DbPool},
 };
-use diesel::{
-  delete,
-  dsl::*,
-  insert_into,
-  result::Error,
-  select,
-  ExpressionMethods,
-  PgConnection,
-  QueryDsl,
-  RunQueryDsl,
-};
+use diesel::{delete, dsl::*, insert_into, result::Error, select, ExpressionMethods, QueryDsl};
+use diesel_async::{AsyncPgConnection, RunQueryDsl};
 use lemmy_utils::error::LemmyError;
-use once_cell::sync::OnceCell;
+use tokio::sync::OnceCell;
 
 impl LocalUserLanguage {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     for_local_user_id: LocalUserId,
   ) -> Result<Vec<LanguageId>, Error> {
     use crate::schema::local_user_language::dsl::*;
-
-    let langs = local_user_language
-      .filter(local_user_id.eq(for_local_user_id))
-      .select(language_id)
-      .get_results(conn)?;
-    convert_read_languages(conn, langs)
+    let conn = &mut get_conn(pool).await?;
+
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          let langs = local_user_language
+            .filter(local_user_id.eq(for_local_user_id))
+            .select(language_id)
+            .get_results(conn)
+            .await?;
+          convert_read_languages(conn, langs).await
+        }) as _
+      })
+      .await
   }
 
   /// Update the user's languages.
   ///
   /// If no language_id vector is given, it will show all languages
-  pub fn update(
-    conn: &mut PgConnection,
+  pub async fn update(
+    pool: &DbPool,
     language_ids: Vec<LanguageId>,
     for_local_user_id: LocalUserId,
   ) -> Result<(), Error> {
-    conn.build_transaction().read_write().run(|conn| {
-      use crate::schema::local_user_language::dsl::*;
-      // Clear the current user languages
-      delete(local_user_language.filter(local_user_id.eq(for_local_user_id))).execute(conn)?;
-
-      let lang_ids = convert_update_languages(conn, language_ids)?;
-      for l in lang_ids {
-        let form = LocalUserLanguageForm {
-          local_user_id: for_local_user_id,
-          language_id: l,
-        };
-        insert_into(local_user_language)
-          .values(form)
-          .get_result::<Self>(conn)?;
-      }
-      Ok(())
-    })
+    let conn = &mut get_conn(pool).await?;
+
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          use crate::schema::local_user_language::dsl::*;
+          // Clear the current user languages
+          delete(local_user_language.filter(local_user_id.eq(for_local_user_id)))
+            .execute(conn)
+            .await?;
+
+          let lang_ids = convert_update_languages(conn, language_ids).await?;
+          for l in lang_ids {
+            let form = LocalUserLanguageForm {
+              local_user_id: for_local_user_id,
+              language_id: l,
+            };
+            insert_into(local_user_language)
+              .values(form)
+              .get_result::<Self>(conn)
+              .await?;
+          }
+          Ok(())
+        }) as _
+      })
+      .await
   }
 }
 
 impl SiteLanguage {
-  pub fn read_local(conn: &mut PgConnection) -> Result<Vec<LanguageId>, Error> {
-    use crate::schema::{local_site, site, site_language};
+  pub async fn read_local(pool: &DbPool) -> Result<Vec<LanguageId>, Error> {
+    let conn = &mut get_conn(pool).await?;
     site::table
       .inner_join(local_site::table)
       .inner_join(site_language::table)
       .select(site_language::language_id)
       .load(conn)
+      .await
   }
 
-  pub fn read(conn: &mut PgConnection, for_site_id: SiteId) -> Result<Vec<LanguageId>, Error> {
-    use crate::schema::site_language::dsl::*;
-    let langs = site_language
-      .filter(site_id.eq(for_site_id))
-      .select(language_id)
-      .load(conn)?;
-    convert_read_languages(conn, langs)
+  pub async fn read(pool: &DbPool, for_site_id: SiteId) -> Result<Vec<LanguageId>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
+    let langs = site_language::table
+      .filter(site_language::site_id.eq(for_site_id))
+      .select(site_language::language_id)
+      .load(conn)
+      .await?;
+    convert_read_languages(conn, langs).await
   }
 
-  pub fn update(
-    conn: &mut PgConnection,
+  pub async fn update(
+    pool: &DbPool,
     language_ids: Vec<LanguageId>,
     site: &Site,
   ) -> Result<(), Error> {
-    conn.build_transaction().read_write().run(|conn| {
-      use crate::schema::site_language::dsl::*;
-      // Clear the current languages
-      delete(site_language.filter(site_id.eq(site.id))).execute(conn)?;
-
-      let lang_ids = convert_update_languages(conn, language_ids)?;
-      for l in lang_ids {
-        let form = SiteLanguageForm {
-          site_id: site.id,
-          language_id: l,
-        };
-        insert_into(site_language)
-          .values(form)
-          .get_result::<Self>(conn)?;
-      }
-
-      CommunityLanguage::limit_languages(conn, site.instance_id)?;
-
-      Ok(())
-    })
+    let conn = &mut get_conn(pool).await?;
+    let for_site_id = site.id;
+    let instance_id = site.instance_id;
+
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          use crate::schema::site_language::dsl::*;
+
+          // Clear the current languages
+          delete(site_language.filter(site_id.eq(for_site_id)))
+            .execute(conn)
+            .await?;
+
+          let lang_ids = convert_update_languages(conn, language_ids).await?;
+          for l in lang_ids {
+            let form = SiteLanguageForm {
+              site_id: for_site_id,
+              language_id: l,
+            };
+            insert_into(site_language)
+              .values(form)
+              .get_result::<Self>(conn)
+              .await?;
+          }
+
+          CommunityLanguage::limit_languages(conn, instance_id).await?;
+
+          Ok(())
+        }) as _
+      })
+      .await
   }
 }
 
 impl CommunityLanguage {
   /// Returns true if the given language is one of configured languages for given community
-  pub fn is_allowed_community_language(
-    conn: &mut PgConnection,
+  pub async fn is_allowed_community_language(
+    pool: &DbPool,
     for_language_id: Option<LanguageId>,
     for_community_id: CommunityId,
   ) -> Result<(), LemmyError> {
     use crate::schema::community_language::dsl::*;
+    let conn = &mut get_conn(pool).await?;
+
     if let Some(for_language_id) = for_language_id {
       let is_allowed = select(exists(
         community_language
           .filter(language_id.eq(for_language_id))
           .filter(community_id.eq(for_community_id)),
       ))
-      .get_result(conn)?;
+      .get_result(conn)
+      .await?;
 
       if is_allowed {
         Ok(())
@@ -136,7 +167,10 @@ impl CommunityLanguage {
   /// also part of site languages. This is because post/comment language is only checked against
   /// community language, and it shouldnt be possible to post content in languages which are not
   /// allowed by local site.
-  fn limit_languages(conn: &mut PgConnection, for_instance_id: InstanceId) -> Result<(), Error> {
+  async fn limit_languages(
+    conn: &mut AsyncPgConnection,
+    for_instance_id: InstanceId,
+  ) -> Result<(), Error> {
     use crate::schema::{
       community::dsl as c,
       community_language::dsl as cl,
@@ -148,65 +182,84 @@ impl CommunityLanguage {
       .filter(c::instance_id.eq(for_instance_id))
       .filter(sl::language_id.is_null())
       .select(cl::language_id)
-      .get_results(conn)?;
+      .get_results(conn)
+      .await?;
 
     for c in community_languages {
-      delete(cl::community_language.filter(cl::language_id.eq(c))).execute(conn)?;
+      delete(cl::community_language.filter(cl::language_id.eq(c)))
+        .execute(conn)
+        .await?;
     }
     Ok(())
   }
 
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     for_community_id: CommunityId,
   ) -> Result<Vec<LanguageId>, Error> {
     use crate::schema::community_language::dsl::*;
+    let conn = &mut get_conn(pool).await?;
+
     let langs = community_language
       .filter(community_id.eq(for_community_id))
       .select(language_id)
-      .get_results(conn)?;
-    convert_read_languages(conn, langs)
+      .get_results(conn)
+      .await?;
+    convert_read_languages(conn, langs).await
   }
 
-  pub fn update(
-    conn: &mut PgConnection,
+  pub async fn update(
+    pool: &DbPool,
     mut language_ids: Vec<LanguageId>,
     for_community_id: CommunityId,
   ) -> Result<(), Error> {
-    conn.build_transaction().read_write().run(|conn| {
-      use crate::schema::community_language::dsl::*;
-      // Clear the current languages
-      delete(community_language.filter(community_id.eq(for_community_id))).execute(conn)?;
+    let conn = &mut get_conn(pool).await?;
 
-      if language_ids.is_empty() {
-        language_ids = SiteLanguage::read_local(conn)?;
-      }
-      for l in language_ids {
-        let form = CommunityLanguageForm {
-          community_id: for_community_id,
-          language_id: l,
-        };
-        insert_into(community_language)
-          .values(form)
-          .get_result::<Self>(conn)?;
-      }
-      Ok(())
-    })
+    if language_ids.is_empty() {
+      language_ids = SiteLanguage::read_local(pool).await?;
+    }
+
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          use crate::schema::community_language::dsl::*;
+          // Clear the current languages
+          delete(community_language.filter(community_id.eq(for_community_id)))
+            .execute(conn)
+            .await?;
+
+          for l in language_ids {
+            let form = CommunityLanguageForm {
+              community_id: for_community_id,
+              language_id: l,
+            };
+            insert_into(community_language)
+              .values(form)
+              .get_result::<Self>(conn)
+              .await?;
+          }
+          Ok(())
+        }) as _
+      })
+      .await
   }
 }
 
-pub fn default_post_language(
-  conn: &mut PgConnection,
+pub async fn default_post_language(
+  pool: &DbPool,
   community_id: CommunityId,
   local_user_id: LocalUserId,
 ) -> Result<Option<LanguageId>, Error> {
+  let conn = &mut get_conn(pool).await?;
   use crate::schema::{community_language::dsl as cl, local_user_language::dsl as ul};
   let intersection = ul::local_user_language
     .inner_join(cl::community_language.on(ul::language_id.eq(cl::language_id)))
     .filter(ul::local_user_id.eq(local_user_id))
     .filter(cl::community_id.eq(community_id))
     .select(cl::language_id)
-    .get_results::<LanguageId>(conn)?;
+    .get_results::<LanguageId>(conn)
+    .await?;
 
   if intersection.len() == 1 {
     Ok(Some(intersection[0]))
@@ -216,13 +269,14 @@ pub fn default_post_language(
 }
 
 /// If no language is given, set all languages
-fn convert_update_languages(
-  conn: &mut PgConnection,
+async fn convert_update_languages(
+  conn: &mut AsyncPgConnection,
   language_ids: Vec<LanguageId>,
 ) -> Result<Vec<LanguageId>, Error> {
   if language_ids.is_empty() {
     Ok(
-      Language::read_all(conn)?
+      Language::read_all_conn(conn)
+        .await?
         .into_iter()
         .map(|l| l.id)
         .collect(),
@@ -233,19 +287,22 @@ fn convert_update_languages(
 }
 
 /// If all languages are returned, return empty vec instead
-fn convert_read_languages(
-  conn: &mut PgConnection,
+async fn convert_read_languages(
+  conn: &mut AsyncPgConnection,
   language_ids: Vec<LanguageId>,
 ) -> Result<Vec<LanguageId>, Error> {
-  static ALL_LANGUAGES_COUNT: OnceCell<usize> = OnceCell::new();
-  let count = ALL_LANGUAGES_COUNT.get_or_init(|| {
-    use crate::schema::language::dsl::*;
-    let count: i64 = language
-      .select(count(id))
-      .first(conn)
-      .expect("read number of languages");
-    count as usize
-  });
+  static ALL_LANGUAGES_COUNT: OnceCell<usize> = OnceCell::const_new();
+  let count = ALL_LANGUAGES_COUNT
+    .get_or_init(|| async {
+      use crate::schema::language::dsl::*;
+      let count: i64 = language
+        .select(count(id))
+        .first(conn)
+        .await
+        .expect("read number of languages");
+      count as usize
+    })
+    .await;
 
   if &language_ids.len() == count {
     Ok(vec![])
@@ -267,145 +324,159 @@ mod tests {
       site::{Site, SiteInsertForm},
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  fn test_langs1(conn: &mut PgConnection) -> Vec<LanguageId> {
+  async fn test_langs1(pool: &DbPool) -> Vec<LanguageId> {
     vec![
-      Language::read_id_from_code(conn, "en").unwrap(),
-      Language::read_id_from_code(conn, "fr").unwrap(),
-      Language::read_id_from_code(conn, "ru").unwrap(),
+      Language::read_id_from_code(pool, "en").await.unwrap(),
+      Language::read_id_from_code(pool, "fr").await.unwrap(),
+      Language::read_id_from_code(pool, "ru").await.unwrap(),
     ]
   }
-  fn test_langs2(conn: &mut PgConnection) -> Vec<LanguageId> {
+  async fn test_langs2(pool: &DbPool) -> Vec<LanguageId> {
     vec![
-      Language::read_id_from_code(conn, "fi").unwrap(),
-      Language::read_id_from_code(conn, "se").unwrap(),
+      Language::read_id_from_code(pool, "fi").await.unwrap(),
+      Language::read_id_from_code(pool, "se").await.unwrap(),
     ]
   }
 
-  fn create_test_site(conn: &mut PgConnection) -> (Site, Instance) {
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+  async fn create_test_site(pool: &DbPool) -> (Site, Instance) {
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let site_form = SiteInsertForm::builder()
       .name("test site".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let site = Site::create(conn, &site_form).unwrap();
+    let site = Site::create(pool, &site_form).await.unwrap();
 
     // Create a local site, since this is necessary for local languages
     let local_site_form = LocalSiteInsertForm::builder().site_id(site.id).build();
-    LocalSite::create(conn, &local_site_form).unwrap();
+    LocalSite::create(pool, &local_site_form).await.unwrap();
 
     (site, inserted_instance)
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_convert_update_languages() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_convert_update_languages() {
+    let pool = &build_db_pool_for_tests().await;
 
     // call with empty vec, returns all languages
-    let converted1 = convert_update_languages(conn, vec![]).unwrap();
+    let conn = &mut get_conn(pool).await.unwrap();
+    let converted1 = convert_update_languages(conn, vec![]).await.unwrap();
     assert_eq!(184, converted1.len());
 
     // call with nonempty vec, returns same vec
-    let test_langs = test_langs1(conn);
-    let converted2 = convert_update_languages(conn, test_langs.clone()).unwrap();
+    let test_langs = test_langs1(pool).await;
+    let converted2 = convert_update_languages(conn, test_langs.clone())
+      .await
+      .unwrap();
     assert_eq!(test_langs, converted2);
   }
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_convert_read_languages() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_convert_read_languages() {
+    let pool = &build_db_pool_for_tests().await;
 
     // call with all languages, returns empty vec
     use crate::schema::language::dsl::*;
-    let all_langs = language.select(id).get_results(conn).unwrap();
-    let converted1: Vec<LanguageId> = convert_read_languages(conn, all_langs).unwrap();
+    let conn = &mut get_conn(pool).await.unwrap();
+    let all_langs = language.select(id).get_results(conn).await.unwrap();
+    let converted1: Vec<LanguageId> = convert_read_languages(conn, all_langs).await.unwrap();
     assert_eq!(0, converted1.len());
 
     // call with nonempty vec, returns same vec
-    let test_langs = test_langs1(conn);
-    let converted2 = convert_read_languages(conn, test_langs.clone()).unwrap();
+    let test_langs = test_langs1(pool).await;
+    let converted2 = convert_read_languages(conn, test_langs.clone())
+      .await
+      .unwrap();
     assert_eq!(test_langs, converted2);
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_site_languages() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_site_languages() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let (site, instance) = create_test_site(conn);
-    let site_languages1 = SiteLanguage::read_local(conn).unwrap();
+    let (site, instance) = create_test_site(pool).await;
+    let site_languages1 = SiteLanguage::read_local(pool).await.unwrap();
     // site is created with all languages
     assert_eq!(184, site_languages1.len());
 
-    let test_langs = test_langs1(conn);
-    SiteLanguage::update(conn, test_langs.clone(), &site).unwrap();
+    let test_langs = test_langs1(pool).await;
+    SiteLanguage::update(pool, test_langs.clone(), &site)
+      .await
+      .unwrap();
 
-    let site_languages2 = SiteLanguage::read_local(conn).unwrap();
+    let site_languages2 = SiteLanguage::read_local(pool).await.unwrap();
     // after update, site only has new languages
     assert_eq!(test_langs, site_languages2);
 
-    Site::delete(conn, site.id).unwrap();
-    Instance::delete(conn, instance.id).unwrap();
-    LocalSite::delete(conn).unwrap();
+    Site::delete(pool, site.id).await.unwrap();
+    Instance::delete(pool, instance.id).await.unwrap();
+    LocalSite::delete(pool).await.unwrap();
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_user_languages() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_user_languages() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let (site, instance) = create_test_site(conn);
-    let test_langs = test_langs1(conn);
-    SiteLanguage::update(conn, test_langs.clone(), &site).unwrap();
+    let (site, instance) = create_test_site(pool).await;
+    let test_langs = test_langs1(pool).await;
+    SiteLanguage::update(pool, test_langs.clone(), &site)
+      .await
+      .unwrap();
 
     let person_form = PersonInsertForm::builder()
       .name("my test person".to_string())
       .public_key("pubkey".to_string())
       .instance_id(instance.id)
       .build();
-    let person = Person::create(conn, &person_form).unwrap();
+    let person = Person::create(pool, &person_form).await.unwrap();
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(person.id)
       .password_encrypted("my_pw".to_string())
       .build();
 
-    let local_user = LocalUser::create(conn, &local_user_form).unwrap();
-    let local_user_langs1 = LocalUserLanguage::read(conn, local_user.id).unwrap();
+    let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
+    let local_user_langs1 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
 
     // new user should be initialized with site languages
     assert_eq!(test_langs, local_user_langs1);
 
     // update user languages
-    let test_langs2 = test_langs2(conn);
-    LocalUserLanguage::update(conn, test_langs2, local_user.id).unwrap();
-    let local_user_langs2 = LocalUserLanguage::read(conn, local_user.id).unwrap();
+    let test_langs2 = test_langs2(pool).await;
+    LocalUserLanguage::update(pool, test_langs2, local_user.id)
+      .await
+      .unwrap();
+    let local_user_langs2 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
     assert_eq!(2, local_user_langs2.len());
 
-    Person::delete(conn, person.id).unwrap();
-    LocalUser::delete(conn, local_user.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
-    LocalSite::delete(conn).unwrap();
-    Instance::delete(conn, instance.id).unwrap();
+    Person::delete(pool, person.id).await.unwrap();
+    LocalUser::delete(pool, local_user.id).await.unwrap();
+    Site::delete(pool, site.id).await.unwrap();
+    LocalSite::delete(pool).await.unwrap();
+    Instance::delete(pool, instance.id).await.unwrap();
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_community_languages() {
-    let conn = &mut establish_unpooled_connection();
-    let (site, instance) = create_test_site(conn);
-    let test_langs = test_langs1(conn);
-    SiteLanguage::update(conn, test_langs.clone(), &site).unwrap();
-
-    let read_site_langs = SiteLanguage::read(conn, site.id).unwrap();
+  async fn test_community_languages() {
+    let pool = &build_db_pool_for_tests().await;
+    let (site, instance) = create_test_site(pool).await;
+    let test_langs = test_langs1(pool).await;
+    SiteLanguage::update(pool, test_langs.clone(), &site)
+      .await
+      .unwrap();
+
+    let read_site_langs = SiteLanguage::read(pool, site.id).await.unwrap();
     assert_eq!(test_langs, read_site_langs);
 
     // Test the local ones are the same
-    let read_local_site_langs = SiteLanguage::read_local(conn).unwrap();
+    let read_local_site_langs = SiteLanguage::read_local(pool).await.unwrap();
     assert_eq!(test_langs, read_local_site_langs);
 
     let community_form = CommunityInsertForm::builder()
@@ -414,45 +485,51 @@ mod tests {
       .public_key("pubkey".to_string())
       .instance_id(instance.id)
       .build();
-    let community = Community::create(conn, &community_form).unwrap();
-    let community_langs1 = CommunityLanguage::read(conn, community.id).unwrap();
+    let community = Community::create(pool, &community_form).await.unwrap();
+    let community_langs1 = CommunityLanguage::read(pool, community.id).await.unwrap();
 
     // community is initialized with site languages
     assert_eq!(test_langs, community_langs1);
 
     let allowed_lang1 =
-      CommunityLanguage::is_allowed_community_language(conn, Some(test_langs[0]), community.id);
+      CommunityLanguage::is_allowed_community_language(pool, Some(test_langs[0]), community.id)
+        .await;
     assert!(allowed_lang1.is_ok());
 
-    let test_langs2 = test_langs2(conn);
+    let test_langs2 = test_langs2(pool).await;
     let allowed_lang2 =
-      CommunityLanguage::is_allowed_community_language(conn, Some(test_langs2[0]), community.id);
+      CommunityLanguage::is_allowed_community_language(pool, Some(test_langs2[0]), community.id)
+        .await;
     assert!(allowed_lang2.is_err());
 
     // limit site languages to en, fi. after this, community languages should be updated to
     // intersection of old languages (en, fr, ru) and (en, fi), which is only fi.
-    SiteLanguage::update(conn, vec![test_langs[0], test_langs2[0]], &site).unwrap();
-    let community_langs2 = CommunityLanguage::read(conn, community.id).unwrap();
+    SiteLanguage::update(pool, vec![test_langs[0], test_langs2[0]], &site)
+      .await
+      .unwrap();
+    let community_langs2 = CommunityLanguage::read(pool, community.id).await.unwrap();
     assert_eq!(vec![test_langs[0]], community_langs2);
 
     // update community languages to different ones
-    CommunityLanguage::update(conn, test_langs2.clone(), community.id).unwrap();
-    let community_langs3 = CommunityLanguage::read(conn, community.id).unwrap();
+    CommunityLanguage::update(pool, test_langs2.clone(), community.id)
+      .await
+      .unwrap();
+    let community_langs3 = CommunityLanguage::read(pool, community.id).await.unwrap();
     assert_eq!(test_langs2, community_langs3);
 
-    Community::delete(conn, community.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
-    LocalSite::delete(conn).unwrap();
-    Instance::delete(conn, instance.id).unwrap();
+    Community::delete(pool, community.id).await.unwrap();
+    Site::delete(pool, site.id).await.unwrap();
+    LocalSite::delete(pool).await.unwrap();
+    Instance::delete(pool, instance.id).await.unwrap();
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_default_post_language() {
-    let conn = &mut establish_unpooled_connection();
-    let (site, instance) = create_test_site(conn);
-    let test_langs = test_langs1(conn);
-    let test_langs2 = test_langs2(conn);
+  async fn test_default_post_language() {
+    let pool = &build_db_pool_for_tests().await;
+    let (site, instance) = create_test_site(pool).await;
+    let test_langs = test_langs1(pool).await;
+    let test_langs2 = test_langs2(pool).await;
 
     let community_form = CommunityInsertForm::builder()
       .name("test community".to_string())
@@ -460,43 +537,53 @@ mod tests {
       .public_key("pubkey".to_string())
       .instance_id(instance.id)
       .build();
-    let community = Community::create(conn, &community_form).unwrap();
-    CommunityLanguage::update(conn, test_langs, community.id).unwrap();
+    let community = Community::create(pool, &community_form).await.unwrap();
+    CommunityLanguage::update(pool, test_langs, community.id)
+      .await
+      .unwrap();
 
     let person_form = PersonInsertForm::builder()
       .name("my test person".to_string())
       .public_key("pubkey".to_string())
       .instance_id(instance.id)
       .build();
-    let person = Person::create(conn, &person_form).unwrap();
+    let person = Person::create(pool, &person_form).await.unwrap();
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(person.id)
       .password_encrypted("my_pw".to_string())
       .build();
-    let local_user = LocalUser::create(conn, &local_user_form).unwrap();
-    LocalUserLanguage::update(conn, test_langs2, local_user.id).unwrap();
+    let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
+    LocalUserLanguage::update(pool, test_langs2, local_user.id)
+      .await
+      .unwrap();
 
     // no overlap in user/community languages, so no default language for post
-    let def1 = default_post_language(conn, community.id, local_user.id).unwrap();
+    let def1 = default_post_language(pool, community.id, local_user.id)
+      .await
+      .unwrap();
     assert_eq!(None, def1);
 
-    let ru = Language::read_id_from_code(conn, "ru").unwrap();
+    let ru = Language::read_id_from_code(pool, "ru").await.unwrap();
     let test_langs3 = vec![
       ru,
-      Language::read_id_from_code(conn, "fi").unwrap(),
-      Language::read_id_from_code(conn, "se").unwrap(),
+      Language::read_id_from_code(pool, "fi").await.unwrap(),
+      Language::read_id_from_code(pool, "se").await.unwrap(),
     ];
-    LocalUserLanguage::update(conn, test_langs3, local_user.id).unwrap();
+    LocalUserLanguage::update(pool, test_langs3, local_user.id)
+      .await
+      .unwrap();
 
     // this time, both have ru as common lang
-    let def2 = default_post_language(conn, community.id, local_user.id).unwrap();
+    let def2 = default_post_language(pool, community.id, local_user.id)
+      .await
+      .unwrap();
     assert_eq!(Some(ru), def2);
 
-    Person::delete(conn, person.id).unwrap();
-    Community::delete(conn, community.id).unwrap();
-    LocalUser::delete(conn, local_user.id).unwrap();
-    Site::delete(conn, site.id).unwrap();
-    LocalSite::delete(conn).unwrap();
-    Instance::delete(conn, instance.id).unwrap();
+    Person::delete(pool, person.id).await.unwrap();
+    Community::delete(pool, community.id).await.unwrap();
+    LocalUser::delete(pool, local_user.id).await.unwrap();
+    Site::delete(pool, site.id).await.unwrap();
+    LocalSite::delete(pool).await.unwrap();
+    Instance::delete(pool, instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs
index d056f1a2..10583203 100644
--- a/crates/db_schema/src/impls/comment.rs
+++ b/crates/db_schema/src/impls/comment.rs
@@ -1,5 +1,6 @@
 use crate::{
   newtypes::{CommentId, DbUrl, PersonId},
+  schema::comment::dsl::*,
   source::comment::{
     Comment,
     CommentInsertForm,
@@ -10,18 +11,19 @@ use crate::{
     CommentUpdateForm,
   },
   traits::{Crud, DeleteableOrRemoveable, Likeable, Saveable},
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use diesel_ltree::Ltree;
 use url::Url;
 
 impl Comment {
-  pub fn permadelete_for_creator(
-    conn: &mut PgConnection,
+  pub async fn permadelete_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(comment.filter(creator_id.eq(for_creator_id)))
       .set((
         content.eq("*Permananently Deleted*"),
@@ -29,25 +31,27 @@ impl Comment {
         updated.eq(naive_now()),
       ))
       .get_results::<Self>(conn)
+      .await
   }
 
-  pub fn update_removed_for_creator(
-    conn: &mut PgConnection,
+  pub async fn update_removed_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
     new_removed: bool,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(comment.filter(creator_id.eq(for_creator_id)))
       .set((removed.eq(new_removed), updated.eq(naive_now())))
       .get_results::<Self>(conn)
+      .await
   }
 
-  pub fn create(
-    conn: &mut PgConnection,
+  pub async fn create(
+    pool: &DbPool,
     comment_form: &CommentInsertForm,
     parent_path: Option<&Ltree>,
   ) -> Result<Comment, Error> {
-    use crate::schema::comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
 
     // Insert, to get the id
     let inserted_comment = insert_into(comment)
@@ -55,7 +59,8 @@ impl Comment {
       .on_conflict(ap_id)
       .do_update()
       .set(comment_form)
-      .get_result::<Self>(conn);
+      .get_result::<Self>(conn)
+      .await;
 
     if let Ok(comment_insert) = inserted_comment {
       let comment_id = comment_insert.id;
@@ -72,7 +77,8 @@ impl Comment {
 
       let updated_comment = diesel::update(comment.find(comment_id))
         .set(path.eq(ltree))
-        .get_result::<Self>(conn);
+        .get_result::<Self>(conn)
+        .await;
 
       // Update the child count for the parent comment_aggregates
       // You could do this with a trigger, but since you have to do this manually anyway,
@@ -101,20 +107,21 @@ where ca.comment_id = c.id",
           top_parent
         );
 
-        sql_query(update_child_count_stmt).execute(conn)?;
+        sql_query(update_child_count_stmt).execute(conn).await?;
       }
       updated_comment
     } else {
       inserted_comment
     }
   }
-  pub fn read_from_apub_id(conn: &mut PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
-    use crate::schema::comment::dsl::*;
+  pub async fn read_from_apub_id(pool: &DbPool, object_id: Url) -> Result<Option<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let object_id: DbUrl = object_id.into();
     Ok(
       comment
         .filter(ap_id.eq(object_id))
         .first::<Comment>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
@@ -134,86 +141,95 @@ where ca.comment_id = c.id",
   }
 }
 
+#[async_trait]
 impl Crud for Comment {
   type InsertForm = CommentInsertForm;
   type UpdateForm = CommentUpdateForm;
   type IdType = CommentId;
-  fn read(conn: &mut PgConnection, comment_id: CommentId) -> Result<Self, Error> {
-    use crate::schema::comment::dsl::*;
-    comment.find(comment_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, comment_id: CommentId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    comment.find(comment_id).first::<Self>(conn).await
   }
 
-  fn delete(conn: &mut PgConnection, comment_id: CommentId) -> Result<usize, Error> {
-    use crate::schema::comment::dsl::*;
-    diesel::delete(comment.find(comment_id)).execute(conn)
+  async fn delete(pool: &DbPool, comment_id: CommentId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(comment.find(comment_id)).execute(conn).await
   }
 
   /// This is unimplemented, use [[Comment::create]]
-  fn create(_conn: &mut PgConnection, _comment_form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(_pool: &DbPool, _comment_form: &Self::InsertForm) -> Result<Self, Error> {
     unimplemented!();
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     comment_id: CommentId,
     comment_form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(comment.find(comment_id))
       .set(comment_form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Likeable for CommentLike {
   type Form = CommentLikeForm;
   type IdType = CommentId;
-  fn like(conn: &mut PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
+  async fn like(pool: &DbPool, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
     use crate::schema::comment_like::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(comment_like)
       .values(comment_like_form)
       .on_conflict((comment_id, person_id))
       .do_update()
       .set(comment_like_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn remove(
-    conn: &mut PgConnection,
-    person_id: PersonId,
-    comment_id: CommentId,
+  async fn remove(
+    pool: &DbPool,
+    person_id_: PersonId,
+    comment_id_: CommentId,
   ) -> Result<usize, Error> {
-    use crate::schema::comment_like::dsl;
+    use crate::schema::comment_like::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
-      dsl::comment_like
-        .filter(dsl::comment_id.eq(comment_id))
-        .filter(dsl::person_id.eq(person_id)),
+      comment_like
+        .filter(comment_id.eq(comment_id_))
+        .filter(person_id.eq(person_id_)),
     )
     .execute(conn)
+    .await
   }
 }
 
+#[async_trait]
 impl Saveable for CommentSaved {
   type Form = CommentSavedForm;
-  fn save(conn: &mut PgConnection, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
+  async fn save(pool: &DbPool, comment_saved_form: &CommentSavedForm) -> Result<Self, Error> {
     use crate::schema::comment_saved::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(comment_saved)
       .values(comment_saved_form)
       .on_conflict((comment_id, person_id))
       .do_update()
       .set(comment_saved_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn unsave(
-    conn: &mut PgConnection,
-    comment_saved_form: &CommentSavedForm,
-  ) -> Result<usize, Error> {
+  async fn unsave(pool: &DbPool, comment_saved_form: &CommentSavedForm) -> Result<usize, Error> {
     use crate::schema::comment_saved::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       comment_saved
         .filter(comment_id.eq(comment_saved_form.comment_id))
         .filter(person_id.eq(comment_saved_form.person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
@@ -236,17 +252,17 @@ mod tests {
       post::*,
     },
     traits::{Crud, Likeable, Saveable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use diesel_ltree::Ltree;
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("terry".into())
@@ -254,7 +270,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community".to_string())
@@ -263,7 +279,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -271,7 +287,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -279,7 +295,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let expected_comment = Comment {
       id: inserted_comment.id,
@@ -304,7 +320,9 @@ mod tests {
       .build();
 
     let inserted_child_comment =
-      Comment::create(conn, &child_comment_form, Some(&inserted_comment.path)).unwrap();
+      Comment::create(pool, &child_comment_form, Some(&inserted_comment.path))
+        .await
+        .unwrap();
 
     // Comment Like
     let comment_like_form = CommentLikeForm {
@@ -314,7 +332,7 @@ mod tests {
       score: 1,
     };
 
-    let inserted_comment_like = CommentLike::like(conn, &comment_like_form).unwrap();
+    let inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap();
 
     let expected_comment_like = CommentLike {
       id: inserted_comment_like.id,
@@ -331,7 +349,7 @@ mod tests {
       person_id: inserted_person.id,
     };
 
-    let inserted_comment_saved = CommentSaved::save(conn, &comment_saved_form).unwrap();
+    let inserted_comment_saved = CommentSaved::save(pool, &comment_saved_form).await.unwrap();
 
     let expected_comment_saved = CommentSaved {
       id: inserted_comment_saved.id,
@@ -344,17 +362,27 @@ mod tests {
       .content(Some("A test comment".into()))
       .build();
 
-    let updated_comment = Comment::update(conn, inserted_comment.id, &comment_update_form).unwrap();
-
-    let read_comment = Comment::read(conn, inserted_comment.id).unwrap();
-    let like_removed = CommentLike::remove(conn, inserted_person.id, inserted_comment.id).unwrap();
-    let saved_removed = CommentSaved::unsave(conn, &comment_saved_form).unwrap();
-    let num_deleted = Comment::delete(conn, inserted_comment.id).unwrap();
-    Comment::delete(conn, inserted_child_comment.id).unwrap();
-    Post::delete(conn, inserted_post.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let updated_comment = Comment::update(pool, inserted_comment.id, &comment_update_form)
+      .await
+      .unwrap();
+
+    let read_comment = Comment::read(pool, inserted_comment.id).await.unwrap();
+    let like_removed = CommentLike::remove(pool, inserted_person.id, inserted_comment.id)
+      .await
+      .unwrap();
+    let saved_removed = CommentSaved::unsave(pool, &comment_saved_form)
+      .await
+      .unwrap();
+    let num_deleted = Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Comment::delete(pool, inserted_child_comment.id)
+      .await
+      .unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_comment, read_comment);
     assert_eq!(expected_comment, inserted_comment);
diff --git a/crates/db_schema/src/impls/comment_reply.rs b/crates/db_schema/src/impls/comment_reply.rs
index 84d6fda5..4c7a38d7 100644
--- a/crates/db_schema/src/impls/comment_reply.rs
+++ b/crates/db_schema/src/impls/comment_reply.rs
@@ -1,21 +1,29 @@
 use crate::{
   newtypes::{CommentId, CommentReplyId, PersonId},
+  schema::comment_reply::dsl::*,
   source::comment_reply::*,
   traits::Crud,
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Crud for CommentReply {
   type InsertForm = CommentReplyInsertForm;
   type UpdateForm = CommentReplyUpdateForm;
   type IdType = CommentReplyId;
-  fn read(conn: &mut PgConnection, comment_reply_id: CommentReplyId) -> Result<Self, Error> {
-    use crate::schema::comment_reply::dsl::*;
-    comment_reply.find(comment_reply_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, comment_reply_id: CommentReplyId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    comment_reply
+      .find(comment_reply_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, comment_reply_form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::comment_reply::dsl::*;
+  async fn create(pool: &DbPool, comment_reply_form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     // since the return here isnt utilized, we dont need to do an update
     // but get_result doesnt return the existing row here
     insert_into(comment_reply)
@@ -24,26 +32,28 @@ impl Crud for CommentReply {
       .do_update()
       .set(comment_reply_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     comment_reply_id: CommentReplyId,
     comment_reply_form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::comment_reply::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(comment_reply.find(comment_reply_id))
       .set(comment_reply_form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
 impl CommentReply {
-  pub fn mark_all_as_read(
-    conn: &mut PgConnection,
+  pub async fn mark_all_as_read(
+    pool: &DbPool,
     for_recipient_id: PersonId,
   ) -> Result<Vec<CommentReply>, Error> {
-    use crate::schema::comment_reply::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(
       comment_reply
         .filter(recipient_id.eq(for_recipient_id))
@@ -51,16 +61,15 @@ impl CommentReply {
     )
     .set(read.eq(true))
     .get_results::<Self>(conn)
+    .await
   }
 
-  pub fn read_by_comment(
-    conn: &mut PgConnection,
-    for_comment_id: CommentId,
-  ) -> Result<Self, Error> {
-    use crate::schema::comment_reply::dsl::*;
+  pub async fn read_by_comment(pool: &DbPool, for_comment_id: CommentId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     comment_reply
       .filter(comment_id.eq(for_comment_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -76,16 +85,16 @@ mod tests {
       post::*,
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("terrylake".into())
@@ -93,7 +102,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let recipient_form = PersonInsertForm::builder()
       .name("terrylakes recipient".into())
@@ -101,7 +110,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_recipient = Person::create(conn, &recipient_form).unwrap();
+    let inserted_recipient = Person::create(pool, &recipient_form).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community lake".to_string())
@@ -110,7 +119,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -118,7 +127,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -126,7 +135,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let comment_reply_form = CommentReplyInsertForm {
       recipient_id: inserted_recipient.id,
@@ -134,7 +143,9 @@ mod tests {
       read: None,
     };
 
-    let inserted_reply = CommentReply::create(conn, &comment_reply_form).unwrap();
+    let inserted_reply = CommentReply::create(pool, &comment_reply_form)
+      .await
+      .unwrap();
 
     let expected_reply = CommentReply {
       id: inserted_reply.id,
@@ -144,18 +155,21 @@ mod tests {
       published: inserted_reply.published,
     };
 
-    let read_reply = CommentReply::read(conn, inserted_reply.id).unwrap();
+    let read_reply = CommentReply::read(pool, inserted_reply.id).await.unwrap();
 
     let comment_reply_update_form = CommentReplyUpdateForm { read: Some(false) };
-    let updated_reply =
-      CommentReply::update(conn, inserted_reply.id, &comment_reply_update_form).unwrap();
-
-    Comment::delete(conn, inserted_comment.id).unwrap();
-    Post::delete(conn, inserted_post.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Person::delete(conn, inserted_recipient.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let updated_reply = CommentReply::update(pool, inserted_reply.id, &comment_reply_update_form)
+      .await
+      .unwrap();
+
+    Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Person::delete(pool, inserted_recipient.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_reply, read_reply);
     assert_eq!(expected_reply, inserted_reply);
diff --git a/crates/db_schema/src/impls/comment_report.rs b/crates/db_schema/src/impls/comment_report.rs
index ebafddab..b299e951 100644
--- a/crates/db_schema/src/impls/comment_report.rs
+++ b/crates/db_schema/src/impls/comment_report.rs
@@ -1,11 +1,14 @@
 use crate::{
   newtypes::{CommentReportId, PersonId},
+  schema::comment_report::dsl::*,
   source::comment_report::{CommentReport, CommentReportForm},
   traits::Reportable,
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Reportable for CommentReport {
   type Form = CommentReportForm;
   type IdType = CommentReportId;
@@ -13,14 +16,12 @@ impl Reportable for CommentReport {
   ///
   /// * `conn` - the postgres connection
   /// * `comment_report_form` - the filled CommentReportForm to insert
-  fn report(
-    conn: &mut PgConnection,
-    comment_report_form: &CommentReportForm,
-  ) -> Result<Self, Error> {
-    use crate::schema::comment_report::dsl::*;
+  async fn report(pool: &DbPool, comment_report_form: &CommentReportForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(comment_report)
       .values(comment_report_form)
       .get_result::<Self>(conn)
+      .await
   }
 
   /// resolve a comment report
@@ -28,19 +29,20 @@ impl Reportable for CommentReport {
   /// * `conn` - the postgres connection
   /// * `report_id` - the id of the report to resolve
   /// * `by_resolver_id` - the id of the user resolving the report
-  fn resolve(
-    conn: &mut PgConnection,
-    report_id: Self::IdType,
+  async fn resolve(
+    pool: &DbPool,
+    report_id_: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::comment_report::dsl::*;
-    update(comment_report.find(report_id))
+    let conn = &mut get_conn(pool).await?;
+    update(comment_report.find(report_id_))
       .set((
         resolved.eq(true),
         resolver_id.eq(by_resolver_id),
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 
   /// unresolve a comment report
@@ -48,18 +50,19 @@ impl Reportable for CommentReport {
   /// * `conn` - the postgres connection
   /// * `report_id` - the id of the report to unresolve
   /// * `by_resolver_id` - the id of the user unresolving the report
-  fn unresolve(
-    conn: &mut PgConnection,
-    report_id: Self::IdType,
+  async fn unresolve(
+    pool: &DbPool,
+    report_id_: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::comment_report::dsl::*;
-    update(comment_report.find(report_id))
+    let conn = &mut get_conn(pool).await?;
+    update(comment_report.find(report_id_))
       .set((
         resolved.eq(false),
         resolver_id.eq(by_resolver_id),
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs
index 47c7b0e0..d23baed9 100644
--- a/crates/db_schema/src/impls/community.rs
+++ b/crates/db_schema/src/impls/community.rs
@@ -1,5 +1,6 @@
 use crate::{
   newtypes::{CommunityId, DbUrl, PersonId},
+  schema::community::dsl::*,
   source::{
     actor_language::{CommunityLanguage, SiteLanguage},
     community::{
@@ -16,18 +17,11 @@ use crate::{
     },
   },
   traits::{ApubActor, Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable},
-  utils::functions::lower,
+  utils::{functions::lower, get_conn, DbPool},
   SubscribedType,
 };
-use diesel::{
-  dsl::*,
-  result::Error,
-  ExpressionMethods,
-  PgConnection,
-  QueryDsl,
-  RunQueryDsl,
-  TextExpressionMethods,
-};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl, TextExpressionMethods};
+use diesel_async::RunQueryDsl;
 
 mod safe_type {
   use crate::{schema::community::*, source::community::Community, traits::ToSafe};
@@ -76,76 +70,86 @@ mod safe_type {
   }
 }
 
+#[async_trait]
 impl Crud for Community {
   type InsertForm = CommunityInsertForm;
   type UpdateForm = CommunityUpdateForm;
   type IdType = CommunityId;
-  fn read(conn: &mut PgConnection, community_id: CommunityId) -> Result<Self, Error> {
-    use crate::schema::community::dsl::*;
-    community.find(community_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, community_id: CommunityId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    community.find(community_id).first::<Self>(conn).await
   }
 
-  fn delete(conn: &mut PgConnection, community_id: CommunityId) -> Result<usize, Error> {
-    use crate::schema::community::dsl::*;
-    diesel::delete(community.find(community_id)).execute(conn)
+  async fn delete(pool: &DbPool, community_id: CommunityId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(community.find(community_id))
+      .execute(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::community::dsl::*;
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let community_ = insert_into(community)
       .values(form)
       .on_conflict(actor_id)
       .do_update()
       .set(form)
-      .get_result::<Self>(conn)?;
+      .get_result::<Self>(conn)
+      .await?;
 
-    let site_languages = SiteLanguage::read_local(conn);
+    let site_languages = SiteLanguage::read_local(pool).await;
     if let Ok(langs) = site_languages {
       // if site exists, init user with site languages
-      CommunityLanguage::update(conn, langs, community_.id)?;
+      CommunityLanguage::update(pool, langs, community_.id).await?;
     } else {
       // otherwise, init with all languages (this only happens during tests)
-      CommunityLanguage::update(conn, vec![], community_.id)?;
+      CommunityLanguage::update(pool, vec![], community_.id).await?;
     }
 
     Ok(community_)
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     community_id: CommunityId,
     form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(community.find(community_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Joinable for CommunityModerator {
   type Form = CommunityModeratorForm;
-  fn join(
-    conn: &mut PgConnection,
+  async fn join(
+    pool: &DbPool,
     community_moderator_form: &CommunityModeratorForm,
   ) -> Result<Self, Error> {
     use crate::schema::community_moderator::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(community_moderator)
       .values(community_moderator_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn leave(
-    conn: &mut PgConnection,
+  async fn leave(
+    pool: &DbPool,
     community_moderator_form: &CommunityModeratorForm,
   ) -> Result<usize, Error> {
     use crate::schema::community_moderator::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       community_moderator
         .filter(community_id.eq(community_moderator_form.community_id))
         .filter(person_id.eq(community_moderator_form.person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
@@ -170,52 +174,63 @@ impl DeleteableOrRemoveable for Community {
 }
 
 impl CommunityModerator {
-  pub fn delete_for_community(
-    conn: &mut PgConnection,
+  pub async fn delete_for_community(
+    pool: &DbPool,
     for_community_id: CommunityId,
   ) -> Result<usize, Error> {
     use crate::schema::community_moderator::dsl::*;
-    diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
+    let conn = &mut get_conn(pool).await?;
+
+    diesel::delete(community_moderator.filter(community_id.eq(for_community_id)))
+      .execute(conn)
+      .await
   }
 
-  pub fn get_person_moderated_communities(
-    conn: &mut PgConnection,
+  pub async fn get_person_moderated_communities(
+    pool: &DbPool,
     for_person_id: PersonId,
   ) -> Result<Vec<CommunityId>, Error> {
     use crate::schema::community_moderator::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     community_moderator
       .filter(person_id.eq(for_person_id))
       .select(community_id)
       .load::<CommunityId>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Bannable for CommunityPersonBan {
   type Form = CommunityPersonBanForm;
-  fn ban(
-    conn: &mut PgConnection,
+  async fn ban(
+    pool: &DbPool,
     community_person_ban_form: &CommunityPersonBanForm,
   ) -> Result<Self, Error> {
     use crate::schema::community_person_ban::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(community_person_ban)
       .values(community_person_ban_form)
       .on_conflict((community_id, person_id))
       .do_update()
       .set(community_person_ban_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn unban(
-    conn: &mut PgConnection,
+  async fn unban(
+    pool: &DbPool,
     community_person_ban_form: &CommunityPersonBanForm,
   ) -> Result<usize, Error> {
     use crate::schema::community_person_ban::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       community_person_ban
         .filter(community_id.eq(community_person_ban_form.community_id))
         .filter(person_id.eq(community_person_ban_form.person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
@@ -235,29 +250,30 @@ impl CommunityFollower {
   }
 }
 
+#[async_trait]
 impl Followable for CommunityFollower {
   type Form = CommunityFollowerForm;
-  fn follow(
-    conn: &mut PgConnection,
+  async fn follow(
+    pool: &DbPool,
     community_follower_form: &CommunityFollowerForm,
   ) -> Result<Self, Error> {
     use crate::schema::community_follower::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(community_follower)
       .values(community_follower_form)
       .on_conflict((community_id, person_id))
       .do_update()
       .set(community_follower_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn follow_accepted(
-    conn: &mut PgConnection,
+  async fn follow_accepted(
+    pool: &DbPool,
     community_id_: CommunityId,
     person_id_: PersonId,
-  ) -> Result<Self, Error>
-  where
-    Self: Sized,
-  {
+  ) -> Result<Self, Error> {
     use crate::schema::community_follower::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(
       community_follower
         .filter(community_id.eq(community_id_))
@@ -265,51 +281,55 @@ impl Followable for CommunityFollower {
     )
     .set(pending.eq(false))
     .get_result::<Self>(conn)
+    .await
   }
-  fn unfollow(
-    conn: &mut PgConnection,
+  async fn unfollow(
+    pool: &DbPool,
     community_follower_form: &CommunityFollowerForm,
   ) -> Result<usize, Error> {
     use crate::schema::community_follower::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       community_follower
         .filter(community_id.eq(&community_follower_form.community_id))
         .filter(person_id.eq(&community_follower_form.person_id)),
     )
     .execute(conn)
+    .await
   }
   // TODO: this function name only makes sense if you call it with a remote community. for a local
   //       community, it will also return true if only remote followers exist
-  fn has_local_followers(
-    conn: &mut PgConnection,
-    community_id_: CommunityId,
-  ) -> Result<bool, Error> {
+  async fn has_local_followers(pool: &DbPool, community_id_: CommunityId) -> Result<bool, Error> {
     use crate::schema::community_follower::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::select(exists(
       community_follower.filter(community_id.eq(community_id_)),
     ))
     .get_result(conn)
+    .await
   }
 }
 
+#[async_trait]
 impl ApubActor for Community {
-  fn read_from_apub_id(conn: &mut PgConnection, object_id: &DbUrl) -> Result<Option<Self>, Error> {
-    use crate::schema::community::dsl::*;
+  async fn read_from_apub_id(pool: &DbPool, object_id: &DbUrl) -> Result<Option<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     Ok(
       community
         .filter(actor_id.eq(object_id))
         .first::<Community>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
   }
 
-  fn read_from_name(
-    conn: &mut PgConnection,
+  async fn read_from_name(
+    pool: &DbPool,
     community_name: &str,
     include_deleted: bool,
   ) -> Result<Community, Error> {
-    use crate::schema::community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let mut q = community
       .into_boxed()
       .filter(local.eq(true))
@@ -317,19 +337,20 @@ impl ApubActor for Community {
     if !include_deleted {
       q = q.filter(deleted.eq(false)).filter(removed.eq(false));
     }
-    q.first::<Self>(conn)
+    q.first::<Self>(conn).await
   }
 
-  fn read_from_name_and_domain(
-    conn: &mut PgConnection,
+  async fn read_from_name_and_domain(
+    pool: &DbPool,
     community_name: &str,
     protocol_domain: &str,
   ) -> Result<Community, Error> {
-    use crate::schema::community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     community
       .filter(lower(name).eq(lower(community_name)))
       .filter(actor_id.like(format!("{}%", protocol_domain)))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -338,16 +359,16 @@ mod tests {
   use crate::{
     source::{community::*, instance::Instance, person::*},
     traits::{Bannable, Crud, Followable, Joinable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("bobbee".into())
@@ -355,7 +376,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("TIL".into())
@@ -364,7 +385,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let expected_community = Community {
       id: inserted_community.id,
@@ -397,8 +418,9 @@ mod tests {
       pending: false,
     };
 
-    let inserted_community_follower =
-      CommunityFollower::follow(conn, &community_follower_form).unwrap();
+    let inserted_community_follower = CommunityFollower::follow(pool, &community_follower_form)
+      .await
+      .unwrap();
 
     let expected_community_follower = CommunityFollower {
       id: inserted_community_follower.id,
@@ -413,8 +435,9 @@ mod tests {
       person_id: inserted_person.id,
     };
 
-    let inserted_community_moderator =
-      CommunityModerator::join(conn, &community_moderator_form).unwrap();
+    let inserted_community_moderator = CommunityModerator::join(pool, &community_moderator_form)
+      .await
+      .unwrap();
 
     let expected_community_moderator = CommunityModerator {
       id: inserted_community_moderator.id,
@@ -429,8 +452,9 @@ mod tests {
       expires: None,
     };
 
-    let inserted_community_person_ban =
-      CommunityPersonBan::ban(conn, &community_person_ban_form).unwrap();
+    let inserted_community_person_ban = CommunityPersonBan::ban(pool, &community_person_ban_form)
+      .await
+      .unwrap();
 
     let expected_community_person_ban = CommunityPersonBan {
       id: inserted_community_person_ban.id,
@@ -440,20 +464,29 @@ mod tests {
       expires: None,
     };
 
-    let read_community = Community::read(conn, inserted_community.id).unwrap();
+    let read_community = Community::read(pool, inserted_community.id).await.unwrap();
 
     let update_community_form = CommunityUpdateForm::builder()
       .title(Some("nada".to_owned()))
       .build();
-    let updated_community =
-      Community::update(conn, inserted_community.id, &update_community_form).unwrap();
-
-    let ignored_community = CommunityFollower::unfollow(conn, &community_follower_form).unwrap();
-    let left_community = CommunityModerator::leave(conn, &community_moderator_form).unwrap();
-    let unban = CommunityPersonBan::unban(conn, &community_person_ban_form).unwrap();
-    let num_deleted = Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let updated_community = Community::update(pool, inserted_community.id, &update_community_form)
+      .await
+      .unwrap();
+
+    let ignored_community = CommunityFollower::unfollow(pool, &community_follower_form)
+      .await
+      .unwrap();
+    let left_community = CommunityModerator::leave(pool, &community_moderator_form)
+      .await
+      .unwrap();
+    let unban = CommunityPersonBan::unban(pool, &community_person_ban_form)
+      .await
+      .unwrap();
+    let num_deleted = Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_community, read_community);
     assert_eq!(expected_community, inserted_community);
diff --git a/crates/db_schema/src/impls/community_block.rs b/crates/db_schema/src/impls/community_block.rs
index 49a86173..9e7d5ffa 100644
--- a/crates/db_schema/src/impls/community_block.rs
+++ b/crates/db_schema/src/impls/community_block.rs
@@ -1,27 +1,33 @@
 use crate::{
+  schema::community_block::dsl::*,
   source::community_block::{CommunityBlock, CommunityBlockForm},
   traits::Blockable,
+  utils::{get_conn, DbPool},
 };
 use diesel::{dsl::*, result::Error, *};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Blockable for CommunityBlock {
   type Form = CommunityBlockForm;
-  fn block(conn: &mut PgConnection, community_block_form: &Self::Form) -> Result<Self, Error> {
-    use crate::schema::community_block::dsl::*;
+  async fn block(pool: &DbPool, community_block_form: &Self::Form) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(community_block)
       .values(community_block_form)
       .on_conflict((person_id, community_id))
       .do_update()
       .set(community_block_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn unblock(conn: &mut PgConnection, community_block_form: &Self::Form) -> Result<usize, Error> {
-    use crate::schema::community_block::dsl::*;
+  async fn unblock(pool: &DbPool, community_block_form: &Self::Form) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       community_block
         .filter(person_id.eq(community_block_form.person_id))
         .filter(community_id.eq(community_block_form.community_id)),
     )
     .execute(conn)
+    .await
   }
 }
diff --git a/crates/db_schema/src/impls/email_verification.rs b/crates/db_schema/src/impls/email_verification.rs
index c6140f4b..5bd57417 100644
--- a/crates/db_schema/src/impls/email_verification.rs
+++ b/crates/db_schema/src/impls/email_verification.rs
@@ -1,34 +1,36 @@
-use crate::{newtypes::LocalUserId, source::email_verification::*};
-use diesel::{
-  dsl::*,
-  insert_into,
-  result::Error,
-  ExpressionMethods,
-  PgConnection,
-  QueryDsl,
-  RunQueryDsl,
+use crate::{
+  newtypes::LocalUserId,
+  schema::email_verification::dsl::*,
+  source::email_verification::*,
+  utils::{get_conn, DbPool},
 };
+use diesel::{dsl::*, insert_into, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl EmailVerification {
-  pub fn create(conn: &mut PgConnection, form: &EmailVerificationForm) -> Result<Self, Error> {
-    use crate::schema::email_verification::dsl::*;
+  pub async fn create(pool: &DbPool, form: &EmailVerificationForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(email_verification)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  pub fn read_for_token(conn: &mut PgConnection, token: &str) -> Result<Self, Error> {
-    use crate::schema::email_verification::dsl::*;
+  pub async fn read_for_token(pool: &DbPool, token: &str) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     email_verification
       .filter(verification_token.eq(token))
       .filter(published.gt(now - 7.days()))
       .first::<Self>(conn)
+      .await
   }
-  pub fn delete_old_tokens_for_local_user(
-    conn: &mut PgConnection,
+  pub async fn delete_old_tokens_for_local_user(
+    pool: &DbPool,
     local_user_id_: LocalUserId,
   ) -> Result<usize, Error> {
-    use crate::schema::email_verification::dsl::*;
-    diesel::delete(email_verification.filter(local_user_id.eq(local_user_id_))).execute(conn)
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(email_verification.filter(local_user_id.eq(local_user_id_)))
+      .execute(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/federation_allowlist.rs b/crates/db_schema/src/impls/federation_allowlist.rs
index 406b0e2c..29b4d01f 100644
--- a/crates/db_schema/src/impls/federation_allowlist.rs
+++ b/crates/db_schema/src/impls/federation_allowlist.rs
@@ -4,59 +4,70 @@ use crate::{
     federation_allowlist::{FederationAllowList, FederationAllowListForm},
     instance::Instance,
   },
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error};
+use diesel_async::{AsyncPgConnection, RunQueryDsl};
 
 impl FederationAllowList {
-  pub fn replace(conn: &mut PgConnection, list_opt: Option<Vec<String>>) -> Result<(), Error> {
-    conn.build_transaction().read_write().run(|conn| {
-      if let Some(list) = list_opt {
-        Self::clear(conn)?;
+  pub async fn replace(pool: &DbPool, list_opt: Option<Vec<String>>) -> Result<(), Error> {
+    let conn = &mut get_conn(pool).await?;
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          if let Some(list) = list_opt {
+            Self::clear(conn).await?;
 
-        for domain in list {
-          // Upsert all of these as instances
-          let instance = Instance::create(conn, &domain)?;
+            for domain in list {
+              // Upsert all of these as instances
+              let instance = Instance::create_conn(conn, &domain).await?;
 
-          let form = FederationAllowListForm {
-            instance_id: instance.id,
-            updated: None,
-          };
-          insert_into(federation_allowlist::table)
-            .values(form)
-            .get_result::<Self>(conn)?;
-        }
-        Ok(())
-      } else {
-        Ok(())
-      }
-    })
+              let form = FederationAllowListForm {
+                instance_id: instance.id,
+                updated: None,
+              };
+              insert_into(federation_allowlist::table)
+                .values(form)
+                .get_result::<Self>(conn)
+                .await?;
+            }
+            Ok(())
+          } else {
+            Ok(())
+          }
+        }) as _
+      })
+      .await
   }
 
-  pub fn clear(conn: &mut PgConnection) -> Result<usize, Error> {
-    diesel::delete(federation_allowlist::table).execute(conn)
+  async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
+    diesel::delete(federation_allowlist::table)
+      .execute(conn)
+      .await
   }
 }
 #[cfg(test)]
 mod tests {
   use crate::{
     source::{federation_allowlist::FederationAllowList, instance::Instance},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_allowlist_insert_and_clear() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_allowlist_insert_and_clear() {
+    let pool = &build_db_pool_for_tests().await;
     let allowed = Some(vec![
       "tld1.xyz".to_string(),
       "tld2.xyz".to_string(),
       "tld3.xyz".to_string(),
     ]);
 
-    FederationAllowList::replace(conn, allowed).unwrap();
+    FederationAllowList::replace(pool, allowed).await.unwrap();
 
-    let allows = Instance::allowlist(conn).unwrap();
+    let allows = Instance::allowlist(pool).await.unwrap();
 
     assert_eq!(3, allows.len());
     assert_eq!(
@@ -71,11 +82,13 @@ mod tests {
     // Now test clearing them via Some(empty vec)
     let clear_allows = Some(Vec::new());
 
-    FederationAllowList::replace(conn, clear_allows).unwrap();
-    let allows = Instance::allowlist(conn).unwrap();
+    FederationAllowList::replace(pool, clear_allows)
+      .await
+      .unwrap();
+    let allows = Instance::allowlist(pool).await.unwrap();
 
     assert_eq!(0, allows.len());
 
-    Instance::delete_all(conn).unwrap();
+    Instance::delete_all(pool).await.unwrap();
   }
 }
diff --git a/crates/db_schema/src/impls/federation_blocklist.rs b/crates/db_schema/src/impls/federation_blocklist.rs
index 58ea4e91..0dd02405 100644
--- a/crates/db_schema/src/impls/federation_blocklist.rs
+++ b/crates/db_schema/src/impls/federation_blocklist.rs
@@ -4,35 +4,46 @@ use crate::{
     federation_blocklist::{FederationBlockList, FederationBlockListForm},
     instance::Instance,
   },
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error};
+use diesel_async::{AsyncPgConnection, RunQueryDsl};
 
 impl FederationBlockList {
-  pub fn replace(conn: &mut PgConnection, list_opt: Option<Vec<String>>) -> Result<(), Error> {
-    conn.build_transaction().read_write().run(|conn| {
-      if let Some(list) = list_opt {
-        Self::clear(conn)?;
+  pub async fn replace(pool: &DbPool, list_opt: Option<Vec<String>>) -> Result<(), Error> {
+    let conn = &mut get_conn(pool).await?;
+    conn
+      .build_transaction()
+      .run(|conn| {
+        Box::pin(async move {
+          if let Some(list) = list_opt {
+            Self::clear(conn).await?;
 
-        for domain in list {
-          // Upsert all of these as instances
-          let instance = Instance::create(conn, &domain)?;
+            for domain in list {
+              // Upsert all of these as instances
+              let instance = Instance::create_conn(conn, &domain).await?;
 
-          let form = FederationBlockListForm {
-            instance_id: instance.id,
-            updated: None,
-          };
-          insert_into(federation_blocklist::table)
-            .values(form)
-            .get_result::<Self>(conn)?;
-        }
-        Ok(())
-      } else {
-        Ok(())
-      }
-    })
+              let form = FederationBlockListForm {
+                instance_id: instance.id,
+                updated: None,
+              };
+              insert_into(federation_blocklist::table)
+                .values(form)
+                .get_result::<Self>(conn)
+                .await?;
+            }
+            Ok(())
+          } else {
+            Ok(())
+          }
+        }) as _
+      })
+      .await
   }
 
-  pub fn clear(conn: &mut PgConnection) -> Result<usize, Error> {
-    diesel::delete(federation_blocklist::table).execute(conn)
+  async fn clear(conn: &mut AsyncPgConnection) -> Result<usize, Error> {
+    diesel::delete(federation_blocklist::table)
+      .execute(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/instance.rs b/crates/db_schema/src/impls/instance.rs
index c2afa6ae..716d638e 100644
--- a/crates/db_schema/src/impls/instance.rs
+++ b/crates/db_schema/src/impls/instance.rs
@@ -2,14 +2,18 @@ use crate::{
   newtypes::InstanceId,
   schema::{federation_allowlist, federation_blocklist, instance},
   source::instance::{Instance, InstanceForm},
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::{AsyncPgConnection, RunQueryDsl};
 use lemmy_utils::utils::generate_domain_url;
 use url::Url;
 
 impl Instance {
-  fn create_from_form(conn: &mut PgConnection, form: &InstanceForm) -> Result<Self, Error> {
+  async fn create_from_form_conn(
+    conn: &mut AsyncPgConnection,
+    form: &InstanceForm,
+  ) -> Result<Self, Error> {
     // Do upsert on domain name conflict
     insert_into(instance::table)
       .values(form)
@@ -17,43 +21,58 @@ impl Instance {
       .do_update()
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
-  pub fn create(conn: &mut PgConnection, domain: &str) -> Result<Self, Error> {
+  pub async fn create(pool: &DbPool, domain: &str) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    Self::create_conn(conn, domain).await
+  }
+  pub async fn create_from_actor_id(pool: &DbPool, actor_id: &Url) -> Result<Self, Error> {
+    let domain = &generate_domain_url(actor_id).expect("actor id missing a domain");
+    Self::create(pool, domain).await
+  }
+  pub async fn create_conn(conn: &mut AsyncPgConnection, domain: &str) -> Result<Self, Error> {
     let form = InstanceForm {
       domain: domain.to_string(),
       updated: Some(naive_now()),
     };
-    Self::create_from_form(conn, &form)
-  }
-  pub fn create_from_actor_id(conn: &mut PgConnection, actor_id: &Url) -> Result<Self, Error> {
-    let domain = &generate_domain_url(actor_id).expect("actor id missing a domain");
-    Self::create(conn, domain)
+    Self::create_from_form_conn(conn, &form).await
   }
-  pub fn delete(conn: &mut PgConnection, instance_id: InstanceId) -> Result<usize, Error> {
-    diesel::delete(instance::table.find(instance_id)).execute(conn)
+  pub async fn delete(pool: &DbPool, instance_id: InstanceId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(instance::table.find(instance_id))
+      .execute(conn)
+      .await
   }
-  pub fn delete_all(conn: &mut PgConnection) -> Result<usize, Error> {
-    diesel::delete(instance::table).execute(conn)
+  pub async fn delete_all(pool: &DbPool) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(instance::table).execute(conn).await
   }
-  pub fn allowlist(conn: &mut PgConnection) -> Result<Vec<String>, Error> {
+  pub async fn allowlist(pool: &DbPool) -> Result<Vec<String>, Error> {
+    let conn = &mut get_conn(pool).await?;
     instance::table
       .inner_join(federation_allowlist::table)
       .select(instance::domain)
       .load::<String>(conn)
+      .await
   }
 
-  pub fn blocklist(conn: &mut PgConnection) -> Result<Vec<String>, Error> {
+  pub async fn blocklist(pool: &DbPool) -> Result<Vec<String>, Error> {
+    let conn = &mut get_conn(pool).await?;
     instance::table
       .inner_join(federation_blocklist::table)
       .select(instance::domain)
       .load::<String>(conn)
+      .await
   }
 
-  pub fn linked(conn: &mut PgConnection) -> Result<Vec<String>, Error> {
+  pub async fn linked(pool: &DbPool) -> Result<Vec<String>, Error> {
+    let conn = &mut get_conn(pool).await?;
     instance::table
       .left_join(federation_blocklist::table)
       .filter(federation_blocklist::id.is_null())
       .select(instance::domain)
       .load::<String>(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/language.rs b/crates/db_schema/src/impls/language.rs
index a56c26d7..9da5663e 100644
--- a/crates/db_schema/src/impls/language.rs
+++ b/crates/db_schema/src/impls/language.rs
@@ -1,28 +1,45 @@
-use crate::{diesel::ExpressionMethods, newtypes::LanguageId, source::language::Language};
-use diesel::{result::Error, PgConnection, QueryDsl, RunQueryDsl};
+use crate::{
+  diesel::ExpressionMethods,
+  newtypes::LanguageId,
+  schema::language::dsl::*,
+  source::language::Language,
+  utils::{get_conn, DbPool},
+};
+use diesel::{result::Error, QueryDsl};
+use diesel_async::{AsyncPgConnection, RunQueryDsl};
 
 impl Language {
-  pub fn read_all(conn: &mut PgConnection) -> Result<Vec<Language>, Error> {
-    use crate::schema::language::dsl::*;
-    language.load::<Self>(conn)
+  pub async fn read_all(pool: &DbPool) -> Result<Vec<Language>, Error> {
+    let conn = &mut get_conn(pool).await?;
+    Self::read_all_conn(conn).await
   }
 
-  pub fn read_from_id(conn: &mut PgConnection, id_: LanguageId) -> Result<Language, Error> {
-    use crate::schema::language::dsl::*;
-    language.filter(id.eq(id_)).first::<Self>(conn)
+  pub async fn read_all_conn(conn: &mut AsyncPgConnection) -> Result<Vec<Language>, Error> {
+    language.load::<Self>(conn).await
   }
 
-  pub fn read_id_from_code(conn: &mut PgConnection, code_: &str) -> Result<LanguageId, Error> {
-    use crate::schema::language::dsl::*;
-    Ok(language.filter(code.eq(code_)).first::<Self>(conn)?.id)
+  pub async fn read_from_id(pool: &DbPool, id_: LanguageId) -> Result<Language, Error> {
+    let conn = &mut get_conn(pool).await?;
+    language.filter(id.eq(id_)).first::<Self>(conn).await
   }
 
-  pub fn read_id_from_code_opt(
-    conn: &mut PgConnection,
+  pub async fn read_id_from_code(pool: &DbPool, code_: &str) -> Result<LanguageId, Error> {
+    let conn = &mut get_conn(pool).await?;
+    Ok(
+      language
+        .filter(code.eq(code_))
+        .first::<Self>(conn)
+        .await?
+        .id,
+    )
+  }
+
+  pub async fn read_id_from_code_opt(
+    pool: &DbPool,
     code_: Option<&str>,
   ) -> Result<Option<LanguageId>, Error> {
     if let Some(code_) = code_ {
-      Ok(Some(Language::read_id_from_code(conn, code_)?))
+      Ok(Some(Language::read_id_from_code(pool, code_).await?))
     } else {
       Ok(None)
     }
@@ -31,15 +48,15 @@ impl Language {
 
 #[cfg(test)]
 mod tests {
-  use crate::{source::language::Language, utils::establish_unpooled_connection};
+  use crate::{source::language::Language, utils::build_db_pool_for_tests};
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_languages() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_languages() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let all = Language::read_all(conn).unwrap();
+    let all = Language::read_all(pool).await.unwrap();
 
     assert_eq!(184, all.len());
     assert_eq!("ak", all[5].code);
diff --git a/crates/db_schema/src/impls/local_site.rs b/crates/db_schema/src/impls/local_site.rs
index 4686ac80..4c6712cb 100644
--- a/crates/db_schema/src/impls/local_site.rs
+++ b/crates/db_schema/src/impls/local_site.rs
@@ -1,21 +1,32 @@
-use crate::{schema::local_site::dsl::*, source::local_site::*};
-use diesel::{dsl::*, result::Error, *};
+use crate::{
+  schema::local_site::dsl::*,
+  source::local_site::*,
+  utils::{get_conn, DbPool},
+};
+use diesel::{dsl::*, result::Error};
+use diesel_async::RunQueryDsl;
 
 impl LocalSite {
-  pub fn create(conn: &mut PgConnection, form: &LocalSiteInsertForm) -> Result<Self, Error> {
+  pub async fn create(pool: &DbPool, form: &LocalSiteInsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(local_site)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
-  pub fn read(conn: &mut PgConnection) -> Result<Self, Error> {
-    local_site.first::<Self>(conn)
+  pub async fn read(pool: &DbPool) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    local_site.first::<Self>(conn).await
   }
-  pub fn update(conn: &mut PgConnection, form: &LocalSiteUpdateForm) -> Result<Self, Error> {
+  pub async fn update(pool: &DbPool, form: &LocalSiteUpdateForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(local_site)
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
-  pub fn delete(conn: &mut PgConnection) -> Result<usize, Error> {
-    diesel::delete(local_site).execute(conn)
+  pub async fn delete(pool: &DbPool) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(local_site).execute(conn).await
   }
 }
diff --git a/crates/db_schema/src/impls/local_site_rate_limit.rs b/crates/db_schema/src/impls/local_site_rate_limit.rs
index 55ab3984..6c467781 100644
--- a/crates/db_schema/src/impls/local_site_rate_limit.rs
+++ b/crates/db_schema/src/impls/local_site_rate_limit.rs
@@ -1,25 +1,29 @@
-use crate::{schema::local_site_rate_limit, source::local_site_rate_limit::*};
-use diesel::{dsl::*, result::Error, *};
+use crate::{
+  schema::local_site_rate_limit,
+  source::local_site_rate_limit::*,
+  utils::{get_conn, DbPool},
+};
+use diesel::{dsl::*, result::Error};
+use diesel_async::RunQueryDsl;
 
 impl LocalSiteRateLimit {
-  pub fn read(conn: &mut PgConnection) -> Result<Self, Error> {
-    local_site_rate_limit::table.first::<Self>(conn)
+  pub async fn read(pool: &DbPool) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    local_site_rate_limit::table.first::<Self>(conn).await
   }
 
-  pub fn create(
-    conn: &mut PgConnection,
-    form: &LocalSiteRateLimitInsertForm,
-  ) -> Result<Self, Error> {
+  pub async fn create(pool: &DbPool, form: &LocalSiteRateLimitInsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(local_site_rate_limit::table)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
-  pub fn update(
-    conn: &mut PgConnection,
-    form: &LocalSiteRateLimitUpdateForm,
-  ) -> Result<Self, Error> {
+  pub async fn update(pool: &DbPool, form: &LocalSiteRateLimitUpdateForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(local_site_rate_limit::table)
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs
index 9f2c1c3c..eb36fce6 100644
--- a/crates/db_schema/src/impls/local_user.rs
+++ b/crates/db_schema/src/impls/local_user.rs
@@ -6,10 +6,11 @@ use crate::{
     local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
   },
   traits::Crud,
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
 use bcrypt::{hash, DEFAULT_COST};
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 mod safe_settings_type {
   use crate::{
@@ -67,11 +68,12 @@ mod safe_settings_type {
 }
 
 impl LocalUser {
-  pub fn update_password(
-    conn: &mut PgConnection,
+  pub async fn update_password(
+    pool: &DbPool,
     local_user_id: LocalUserId,
     new_password: &str,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
 
     diesel::update(local_user.find(local_user_id))
@@ -80,34 +82,45 @@ impl LocalUser {
         validator_time.eq(naive_now()),
       ))
       .get_result::<Self>(conn)
+      .await
   }
 
-  pub fn set_all_users_email_verified(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
+  pub async fn set_all_users_email_verified(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(local_user)
       .set(email_verified.eq(true))
       .get_results::<Self>(conn)
+      .await
   }
 
-  pub fn set_all_users_registration_applications_accepted(
-    conn: &mut PgConnection,
+  pub async fn set_all_users_registration_applications_accepted(
+    pool: &DbPool,
   ) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(local_user)
       .set(accepted_application.eq(true))
       .get_results::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for LocalUser {
   type InsertForm = LocalUserInsertForm;
   type UpdateForm = LocalUserUpdateForm;
   type IdType = LocalUserId;
-  fn read(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
-    local_user.find(local_user_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    local_user.find(local_user_id).first::<Self>(conn).await
   }
-  fn delete(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<usize, Error> {
-    diesel::delete(local_user.find(local_user_id)).execute(conn)
+  async fn delete(pool: &DbPool, local_user_id: LocalUserId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(local_user.find(local_user_id))
+      .execute(conn)
+      .await
   }
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let mut form_with_encrypted_password = form.clone();
     let password_hash =
       hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
@@ -115,27 +128,31 @@ impl Crud for LocalUser {
 
     let local_user_ = insert_into(local_user)
       .values(form_with_encrypted_password)
-      .get_result::<Self>(conn)?;
+      .get_result::<Self>(conn)
+      .await
+      .expect("couldnt create local user");
 
-    let site_languages = SiteLanguage::read_local(conn);
+    let site_languages = SiteLanguage::read_local(pool).await;
     if let Ok(langs) = site_languages {
       // if site exists, init user with site languages
-      LocalUserLanguage::update(conn, langs, local_user_.id)?;
+      LocalUserLanguage::update(pool, langs, local_user_.id).await?;
     } else {
       // otherwise, init with all languages (this only happens during tests and
       // for first admin user, which is created before site)
-      LocalUserLanguage::update(conn, vec![], local_user_.id)?;
+      LocalUserLanguage::update(pool, vec![], local_user_.id).await?;
     }
 
     Ok(local_user_)
   }
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     local_user_id: LocalUserId,
     form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(local_user.find(local_user_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/moderator.rs b/crates/db_schema/src/impls/moderator.rs
index 824001de..c9d5a94f 100644
--- a/crates/db_schema/src/impls/moderator.rs
+++ b/crates/db_schema/src/impls/moderator.rs
@@ -1,394 +1,480 @@
-use crate::{source::moderator::*, traits::Crud};
-use diesel::{dsl::*, result::Error, *};
-
-// TODO grep for ..xxxDefault()
-
+use crate::{
+  source::moderator::*,
+  traits::Crud,
+  utils::{get_conn, DbPool},
+};
+use diesel::{dsl::*, result::Error, QueryDsl};
+use diesel_async::RunQueryDsl;
+
+#[async_trait]
 impl Crud for ModRemovePost {
   type InsertForm = ModRemovePostForm;
   type UpdateForm = ModRemovePostForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_remove_post::dsl::*;
-    mod_remove_post.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_remove_post.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModRemovePostForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModRemovePostForm) -> Result<Self, Error> {
     use crate::schema::mod_remove_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_remove_post)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
-    from_id: i32,
-    form: &ModRemovePostForm,
-  ) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModRemovePostForm) -> Result<Self, Error> {
     use crate::schema::mod_remove_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_remove_post.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModLockPost {
   type InsertForm = ModLockPostForm;
   type UpdateForm = ModLockPostForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_lock_post::dsl::*;
-    mod_lock_post.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_lock_post.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModLockPostForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModLockPostForm) -> Result<Self, Error> {
     use crate::schema::mod_lock_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_lock_post)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &ModLockPostForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModLockPostForm) -> Result<Self, Error> {
     use crate::schema::mod_lock_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_lock_post.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModStickyPost {
   type InsertForm = ModStickyPostForm;
   type UpdateForm = ModStickyPostForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_sticky_post::dsl::*;
-    mod_sticky_post.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_sticky_post.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModStickyPostForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModStickyPostForm) -> Result<Self, Error> {
     use crate::schema::mod_sticky_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_sticky_post)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
-    from_id: i32,
-    form: &ModStickyPostForm,
-  ) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModStickyPostForm) -> Result<Self, Error> {
     use crate::schema::mod_sticky_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_sticky_post.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModRemoveComment {
   type InsertForm = ModRemoveCommentForm;
   type UpdateForm = ModRemoveCommentForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_remove_comment::dsl::*;
-    mod_remove_comment.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_remove_comment.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModRemoveCommentForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModRemoveCommentForm) -> Result<Self, Error> {
     use crate::schema::mod_remove_comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_remove_comment)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
-    from_id: i32,
-    form: &ModRemoveCommentForm,
-  ) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModRemoveCommentForm) -> Result<Self, Error> {
     use crate::schema::mod_remove_comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_remove_comment.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModRemoveCommunity {
   type InsertForm = ModRemoveCommunityForm;
   type UpdateForm = ModRemoveCommunityForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_remove_community::dsl::*;
-    mod_remove_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_remove_community.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModRemoveCommunityForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModRemoveCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_remove_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_remove_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     from_id: i32,
     form: &ModRemoveCommunityForm,
   ) -> Result<Self, Error> {
     use crate::schema::mod_remove_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_remove_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModBanFromCommunity {
   type InsertForm = ModBanFromCommunityForm;
   type UpdateForm = ModBanFromCommunityForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_ban_from_community::dsl::*;
-    mod_ban_from_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_ban_from_community
+      .find(from_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModBanFromCommunityForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModBanFromCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_ban_from_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_ban_from_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     from_id: i32,
     form: &ModBanFromCommunityForm,
   ) -> Result<Self, Error> {
     use crate::schema::mod_ban_from_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_ban_from_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModBan {
   type InsertForm = ModBanForm;
   type UpdateForm = ModBanForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_ban::dsl::*;
-    mod_ban.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_ban.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModBanForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModBanForm) -> Result<Self, Error> {
     use crate::schema::mod_ban::dsl::*;
-    insert_into(mod_ban).values(form).get_result::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    insert_into(mod_ban)
+      .values(form)
+      .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &ModBanForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModBanForm) -> Result<Self, Error> {
     use crate::schema::mod_ban::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_ban.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModHideCommunity {
   type InsertForm = ModHideCommunityForm;
   type UpdateForm = ModHideCommunityForm;
   type IdType = i32;
 
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_hide_community::dsl::*;
-    mod_hide_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_hide_community.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModHideCommunityForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModHideCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_hide_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_hide_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
-    from_id: i32,
-    form: &ModHideCommunityForm,
-  ) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModHideCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_hide_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_hide_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModAddCommunity {
   type InsertForm = ModAddCommunityForm;
   type UpdateForm = ModAddCommunityForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_add_community::dsl::*;
-    mod_add_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_add_community.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModAddCommunityForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModAddCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_add_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_add_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
-    from_id: i32,
-    form: &ModAddCommunityForm,
-  ) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModAddCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_add_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_add_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModTransferCommunity {
   type InsertForm = ModTransferCommunityForm;
   type UpdateForm = ModTransferCommunityForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_transfer_community::dsl::*;
-    mod_transfer_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_transfer_community
+      .find(from_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModTransferCommunityForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModTransferCommunityForm) -> Result<Self, Error> {
     use crate::schema::mod_transfer_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(mod_transfer_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     from_id: i32,
     form: &ModTransferCommunityForm,
   ) -> Result<Self, Error> {
     use crate::schema::mod_transfer_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_transfer_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for ModAdd {
   type InsertForm = ModAddForm;
   type UpdateForm = ModAddForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::mod_add::dsl::*;
-    mod_add.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    mod_add.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &ModAddForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &ModAddForm) -> Result<Self, Error> {
     use crate::schema::mod_add::dsl::*;
-    insert_into(mod_add).values(form).get_result::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    insert_into(mod_add)
+      .values(form)
+      .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &ModAddForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &ModAddForm) -> Result<Self, Error> {
     use crate::schema::mod_add::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(mod_add.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for AdminPurgePerson {
   type InsertForm = AdminPurgePersonForm;
   type UpdateForm = AdminPurgePersonForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::admin_purge_person::dsl::*;
-    admin_purge_person.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    admin_purge_person.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_person::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(admin_purge_person)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_person::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(admin_purge_person.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for AdminPurgeCommunity {
   type InsertForm = AdminPurgeCommunityForm;
   type UpdateForm = AdminPurgeCommunityForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::admin_purge_community::dsl::*;
-    admin_purge_community.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    admin_purge_community
+      .find(from_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(admin_purge_community)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_community::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(admin_purge_community.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for AdminPurgePost {
   type InsertForm = AdminPurgePostForm;
   type UpdateForm = AdminPurgePostForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::admin_purge_post::dsl::*;
-    admin_purge_post.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    admin_purge_post.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(admin_purge_post)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(admin_purge_post.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Crud for AdminPurgeComment {
   type InsertForm = AdminPurgeCommentForm;
   type UpdateForm = AdminPurgeCommentForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, from_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, from_id: i32) -> Result<Self, Error> {
     use crate::schema::admin_purge_comment::dsl::*;
-    admin_purge_comment.find(from_id).first::<Self>(conn)
+    let conn = &mut get_conn(pool).await?;
+    admin_purge_comment.find(from_id).first::<Self>(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(admin_purge_comment)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(conn: &mut PgConnection, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
+  async fn update(pool: &DbPool, from_id: i32, form: &Self::InsertForm) -> Result<Self, Error> {
     use crate::schema::admin_purge_comment::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(admin_purge_comment.find(from_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
@@ -397,17 +483,15 @@ mod tests {
   use crate::{
     source::{comment::*, community::*, instance::Instance, moderator::*, person::*, post::*},
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
-
-  // use Crud;
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_mod = PersonInsertForm::builder()
       .name("the mod".into())
@@ -415,7 +499,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_mod = Person::create(conn, &new_mod).unwrap();
+    let inserted_mod = Person::create(pool, &new_mod).await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("jim2".into())
@@ -423,7 +507,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("mod_community".to_string())
@@ -432,7 +516,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post thweep".into())
@@ -440,7 +524,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -448,7 +532,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     // Now the actual tests
 
@@ -459,8 +543,12 @@ mod tests {
       reason: None,
       removed: None,
     };
-    let inserted_mod_remove_post = ModRemovePost::create(conn, &mod_remove_post_form).unwrap();
-    let read_mod_remove_post = ModRemovePost::read(conn, inserted_mod_remove_post.id).unwrap();
+    let inserted_mod_remove_post = ModRemovePost::create(pool, &mod_remove_post_form)
+      .await
+      .unwrap();
+    let read_mod_remove_post = ModRemovePost::read(pool, inserted_mod_remove_post.id)
+      .await
+      .unwrap();
     let expected_mod_remove_post = ModRemovePost {
       id: inserted_mod_remove_post.id,
       post_id: inserted_post.id,
@@ -477,8 +565,12 @@ mod tests {
       post_id: inserted_post.id,
       locked: None,
     };
-    let inserted_mod_lock_post = ModLockPost::create(conn, &mod_lock_post_form).unwrap();
-    let read_mod_lock_post = ModLockPost::read(conn, inserted_mod_lock_post.id).unwrap();
+    let inserted_mod_lock_post = ModLockPost::create(pool, &mod_lock_post_form)
+      .await
+      .unwrap();
+    let read_mod_lock_post = ModLockPost::read(pool, inserted_mod_lock_post.id)
+      .await
+      .unwrap();
     let expected_mod_lock_post = ModLockPost {
       id: inserted_mod_lock_post.id,
       post_id: inserted_post.id,
@@ -494,8 +586,12 @@ mod tests {
       post_id: inserted_post.id,
       stickied: None,
     };
-    let inserted_mod_sticky_post = ModStickyPost::create(conn, &mod_sticky_post_form).unwrap();
-    let read_mod_sticky_post = ModStickyPost::read(conn, inserted_mod_sticky_post.id).unwrap();
+    let inserted_mod_sticky_post = ModStickyPost::create(pool, &mod_sticky_post_form)
+      .await
+      .unwrap();
+    let read_mod_sticky_post = ModStickyPost::read(pool, inserted_mod_sticky_post.id)
+      .await
+      .unwrap();
     let expected_mod_sticky_post = ModStickyPost {
       id: inserted_mod_sticky_post.id,
       post_id: inserted_post.id,
@@ -512,10 +608,12 @@ mod tests {
       reason: None,
       removed: None,
     };
-    let inserted_mod_remove_comment =
-      ModRemoveComment::create(conn, &mod_remove_comment_form).unwrap();
-    let read_mod_remove_comment =
-      ModRemoveComment::read(conn, inserted_mod_remove_comment.id).unwrap();
+    let inserted_mod_remove_comment = ModRemoveComment::create(pool, &mod_remove_comment_form)
+      .await
+      .unwrap();
+    let read_mod_remove_comment = ModRemoveComment::read(pool, inserted_mod_remove_comment.id)
+      .await
+      .unwrap();
     let expected_mod_remove_comment = ModRemoveComment {
       id: inserted_mod_remove_comment.id,
       comment_id: inserted_comment.id,
@@ -535,9 +633,13 @@ mod tests {
       expires: None,
     };
     let inserted_mod_remove_community =
-      ModRemoveCommunity::create(conn, &mod_remove_community_form).unwrap();
+      ModRemoveCommunity::create(pool, &mod_remove_community_form)
+        .await
+        .unwrap();
     let read_mod_remove_community =
-      ModRemoveCommunity::read(conn, inserted_mod_remove_community.id).unwrap();
+      ModRemoveCommunity::read(pool, inserted_mod_remove_community.id)
+        .await
+        .unwrap();
     let expected_mod_remove_community = ModRemoveCommunity {
       id: inserted_mod_remove_community.id,
       community_id: inserted_community.id,
@@ -559,9 +661,13 @@ mod tests {
       expires: None,
     };
     let inserted_mod_ban_from_community =
-      ModBanFromCommunity::create(conn, &mod_ban_from_community_form).unwrap();
+      ModBanFromCommunity::create(pool, &mod_ban_from_community_form)
+        .await
+        .unwrap();
     let read_mod_ban_from_community =
-      ModBanFromCommunity::read(conn, inserted_mod_ban_from_community.id).unwrap();
+      ModBanFromCommunity::read(pool, inserted_mod_ban_from_community.id)
+        .await
+        .unwrap();
     let expected_mod_ban_from_community = ModBanFromCommunity {
       id: inserted_mod_ban_from_community.id,
       community_id: inserted_community.id,
@@ -582,8 +688,8 @@ mod tests {
       banned: None,
       expires: None,
     };
-    let inserted_mod_ban = ModBan::create(conn, &mod_ban_form).unwrap();
-    let read_mod_ban = ModBan::read(conn, inserted_mod_ban.id).unwrap();
+    let inserted_mod_ban = ModBan::create(pool, &mod_ban_form).await.unwrap();
+    let read_mod_ban = ModBan::read(pool, inserted_mod_ban.id).await.unwrap();
     let expected_mod_ban = ModBan {
       id: inserted_mod_ban.id,
       mod_person_id: inserted_mod.id,
@@ -602,10 +708,12 @@ mod tests {
       community_id: inserted_community.id,
       removed: None,
     };
-    let inserted_mod_add_community =
-      ModAddCommunity::create(conn, &mod_add_community_form).unwrap();
-    let read_mod_add_community =
-      ModAddCommunity::read(conn, inserted_mod_add_community.id).unwrap();
+    let inserted_mod_add_community = ModAddCommunity::create(pool, &mod_add_community_form)
+      .await
+      .unwrap();
+    let read_mod_add_community = ModAddCommunity::read(pool, inserted_mod_add_community.id)
+      .await
+      .unwrap();
     let expected_mod_add_community = ModAddCommunity {
       id: inserted_mod_add_community.id,
       community_id: inserted_community.id,
@@ -622,8 +730,8 @@ mod tests {
       other_person_id: inserted_person.id,
       removed: None,
     };
-    let inserted_mod_add = ModAdd::create(conn, &mod_add_form).unwrap();
-    let read_mod_add = ModAdd::read(conn, inserted_mod_add.id).unwrap();
+    let inserted_mod_add = ModAdd::create(pool, &mod_add_form).await.unwrap();
+    let read_mod_add = ModAdd::read(pool, inserted_mod_add.id).await.unwrap();
     let expected_mod_add = ModAdd {
       id: inserted_mod_add.id,
       mod_person_id: inserted_mod.id,
@@ -632,12 +740,14 @@ mod tests {
       when_: inserted_mod_add.when_,
     };
 
-    Comment::delete(conn, inserted_comment.id).unwrap();
-    Post::delete(conn, inserted_post.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Person::delete(conn, inserted_mod.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Person::delete(pool, inserted_mod.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_mod_remove_post, read_mod_remove_post);
     assert_eq!(expected_mod_lock_post, read_mod_lock_post);
diff --git a/crates/db_schema/src/impls/password_reset_request.rs b/crates/db_schema/src/impls/password_reset_request.rs
index 7a4d4c83..fb6873d9 100644
--- a/crates/db_schema/src/impls/password_reset_request.rs
+++ b/crates/db_schema/src/impls/password_reset_request.rs
@@ -3,38 +3,47 @@ use crate::{
   schema::password_reset_request::dsl::*,
   source::password_reset_request::*,
   traits::Crud,
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, PgConnection, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use sha2::{Digest, Sha256};
 
+#[async_trait]
 impl Crud for PasswordResetRequest {
   type InsertForm = PasswordResetRequestForm;
   type UpdateForm = PasswordResetRequestForm;
   type IdType = i32;
-  fn read(conn: &mut PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, password_reset_request_id: i32) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     password_reset_request
       .find(password_reset_request_id)
       .first::<Self>(conn)
+      .await
   }
-  fn create(conn: &mut PgConnection, form: &PasswordResetRequestForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &PasswordResetRequestForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(password_reset_request)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     password_reset_request_id: i32,
     form: &PasswordResetRequestForm,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(password_reset_request.find(password_reset_request_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
 impl PasswordResetRequest {
-  pub fn create_token(
-    conn: &mut PgConnection,
+  pub async fn create_token(
+    pool: &DbPool,
     from_local_user_id: LocalUserId,
     token: &str,
   ) -> Result<PasswordResetRequest, Error> {
@@ -47,12 +56,10 @@ impl PasswordResetRequest {
       token_encrypted: token_hash,
     };
 
-    Self::create(conn, &form)
+    Self::create(pool, &form).await
   }
-  pub fn read_from_token(
-    conn: &mut PgConnection,
-    token: &str,
-  ) -> Result<PasswordResetRequest, Error> {
+  pub async fn read_from_token(pool: &DbPool, token: &str) -> Result<PasswordResetRequest, Error> {
+    let conn = &mut get_conn(pool).await?;
     let mut hasher = Sha256::new();
     hasher.update(token);
     let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
@@ -60,6 +67,7 @@ impl PasswordResetRequest {
       .filter(token_encrypted.eq(token_hash))
       .filter(published.gt(now - 1.days()))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -81,16 +89,16 @@ mod tests {
       person::*,
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("thommy prw".into())
@@ -98,20 +106,22 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let new_local_user = LocalUserInsertForm::builder()
       .person_id(inserted_person.id)
       .password_encrypted("pass".to_string())
       .build();
 
-    let inserted_local_user = LocalUser::create(conn, &new_local_user).unwrap();
+    let inserted_local_user = LocalUser::create(pool, &new_local_user).await.unwrap();
 
     let token = "nope";
     let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
 
     let inserted_password_reset_request =
-      PasswordResetRequest::create_token(conn, inserted_local_user.id, token).unwrap();
+      PasswordResetRequest::create_token(pool, inserted_local_user.id, token)
+        .await
+        .unwrap();
 
     let expected_password_reset_request = PasswordResetRequest {
       id: inserted_password_reset_request.id,
@@ -120,9 +130,11 @@ mod tests {
       published: inserted_password_reset_request.published,
     };
 
-    let read_password_reset_request = PasswordResetRequest::read_from_token(conn, token).unwrap();
-    let num_deleted = Person::delete(conn, inserted_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let read_password_reset_request = PasswordResetRequest::read_from_token(pool, token)
+      .await
+      .unwrap();
+    let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_password_reset_request, read_password_reset_request);
     assert_eq!(
diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs
index 22a26440..17467775 100644
--- a/crates/db_schema/src/impls/person.rs
+++ b/crates/db_schema/src/impls/person.rs
@@ -3,17 +3,10 @@ use crate::{
   schema::person::dsl::*,
   source::person::{Person, PersonInsertForm, PersonUpdateForm},
   traits::{ApubActor, Crud},
-  utils::{functions::lower, naive_now},
-};
-use diesel::{
-  dsl::*,
-  result::Error,
-  ExpressionMethods,
-  PgConnection,
-  QueryDsl,
-  RunQueryDsl,
-  TextExpressionMethods,
+  utils::{functions::lower, get_conn, naive_now, DbPool},
 };
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl, TextExpressionMethods};
+use diesel_async::RunQueryDsl;
 
 mod safe_type {
   use crate::{schema::person::columns::*, source::person::Person, traits::ToSafe};
@@ -68,41 +61,50 @@ mod safe_type {
   }
 }
 
+#[async_trait]
 impl Crud for Person {
   type InsertForm = PersonInsertForm;
   type UpdateForm = PersonUpdateForm;
   type IdType = PersonId;
-  fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
+  async fn read(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     person
       .filter(deleted.eq(false))
       .find(person_id)
       .first::<Self>(conn)
+      .await
   }
-  fn delete(conn: &mut PgConnection, person_id: PersonId) -> Result<usize, Error> {
-    diesel::delete(person.find(person_id)).execute(conn)
+  async fn delete(pool: &DbPool, person_id: PersonId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(person.find(person_id)).execute(conn).await
   }
-  fn create(conn: &mut PgConnection, form: &PersonInsertForm) -> Result<Self, Error> {
+  async fn create(pool: &DbPool, form: &PersonInsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(person)
       .values(form)
       .on_conflict(actor_id)
       .do_update()
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     person_id: PersonId,
     form: &PersonUpdateForm,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::update(person.find(person_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
 impl Person {
-  pub fn delete_account(conn: &mut PgConnection, person_id: PersonId) -> Result<Person, Error> {
+  pub async fn delete_account(pool: &DbPool, person_id: PersonId) -> Result<Person, Error> {
     use crate::schema::local_user;
+    let conn = &mut get_conn(pool).await?;
 
     // Set the local user info to none
     diesel::update(local_user::table.filter(local_user::person_id.eq(person_id)))
@@ -110,7 +112,8 @@ impl Person {
         local_user::email.eq::<Option<String>>(None),
         local_user::validator_time.eq(naive_now()),
       ))
-      .execute(conn)?;
+      .execute(conn)
+      .await?;
 
     diesel::update(person.find(person_id))
       .set((
@@ -123,6 +126,7 @@ impl Person {
         updated.eq(naive_now()),
       ))
       .get_result::<Self>(conn)
+      .await
   }
 }
 
@@ -134,24 +138,27 @@ pub fn is_banned(banned_: bool, expires: Option<chrono::NaiveDateTime>) -> bool
   }
 }
 
+#[async_trait]
 impl ApubActor for Person {
-  fn read_from_apub_id(conn: &mut PgConnection, object_id: &DbUrl) -> Result<Option<Self>, Error> {
-    use crate::schema::person::dsl::*;
+  async fn read_from_apub_id(pool: &DbPool, object_id: &DbUrl) -> Result<Option<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     Ok(
       person
         .filter(deleted.eq(false))
         .filter(actor_id.eq(object_id))
         .first::<Person>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
   }
 
-  fn read_from_name(
-    conn: &mut PgConnection,
+  async fn read_from_name(
+    pool: &DbPool,
     from_name: &str,
     include_deleted: bool,
   ) -> Result<Person, Error> {
+    let conn = &mut get_conn(pool).await?;
     let mut q = person
       .into_boxed()
       .filter(local.eq(true))
@@ -159,19 +166,20 @@ impl ApubActor for Person {
     if !include_deleted {
       q = q.filter(deleted.eq(false))
     }
-    q.first::<Self>(conn)
+    q.first::<Self>(conn).await
   }
 
-  fn read_from_name_and_domain(
-    conn: &mut PgConnection,
+  async fn read_from_name_and_domain(
+    pool: &DbPool,
     person_name: &str,
     protocol_domain: &str,
   ) -> Result<Person, Error> {
-    use crate::schema::person::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     person
       .filter(lower(name).eq(lower(person_name)))
       .filter(actor_id.like(format!("{}%", protocol_domain)))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -180,16 +188,16 @@ mod tests {
   use crate::{
     source::{instance::Instance, person::*},
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("holly".into())
@@ -197,7 +205,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let expected_person = Person {
       id: inserted_person.id,
@@ -224,15 +232,17 @@ mod tests {
       instance_id: inserted_instance.id,
     };
 
-    let read_person = Person::read(conn, inserted_person.id).unwrap();
+    let read_person = Person::read(pool, inserted_person.id).await.unwrap();
 
     let update_person_form = PersonUpdateForm::builder()
       .actor_id(Some(inserted_person.actor_id.to_owned()))
       .build();
-    let updated_person = Person::update(conn, inserted_person.id, &update_person_form).unwrap();
+    let updated_person = Person::update(pool, inserted_person.id, &update_person_form)
+      .await
+      .unwrap();
 
-    let num_deleted = Person::delete(conn, inserted_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_person, read_person);
     assert_eq!(expected_person, inserted_person);
diff --git a/crates/db_schema/src/impls/person_block.rs b/crates/db_schema/src/impls/person_block.rs
index 6ee617d6..0158a327 100644
--- a/crates/db_schema/src/impls/person_block.rs
+++ b/crates/db_schema/src/impls/person_block.rs
@@ -1,42 +1,49 @@
 use crate::{
   newtypes::PersonId,
+  schema::person_block::dsl::*,
   source::person_block::{PersonBlock, PersonBlockForm},
   traits::Blockable,
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
 impl PersonBlock {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     for_person_id: PersonId,
     for_recipient_id: PersonId,
   ) -> Result<Self, Error> {
-    use crate::schema::person_block::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     person_block
       .filter(person_id.eq(for_person_id))
       .filter(target_id.eq(for_recipient_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
+#[async_trait]
 impl Blockable for PersonBlock {
   type Form = PersonBlockForm;
-  fn block(conn: &mut PgConnection, person_block_form: &PersonBlockForm) -> Result<Self, Error> {
-    use crate::schema::person_block::dsl::*;
+  async fn block(pool: &DbPool, person_block_form: &PersonBlockForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(person_block)
       .values(person_block_form)
       .on_conflict((person_id, target_id))
       .do_update()
       .set(person_block_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn unblock(conn: &mut PgConnection, person_block_form: &Self::Form) -> Result<usize, Error> {
-    use crate::schema::person_block::dsl::*;
+  async fn unblock(pool: &DbPool, person_block_form: &Self::Form) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       person_block
         .filter(person_id.eq(person_block_form.person_id))
         .filter(target_id.eq(person_block_form.target_id)),
     )
     .execute(conn)
+    .await
   }
 }
diff --git a/crates/db_schema/src/impls/person_mention.rs b/crates/db_schema/src/impls/person_mention.rs
index e83de1fe..d902e951 100644
--- a/crates/db_schema/src/impls/person_mention.rs
+++ b/crates/db_schema/src/impls/person_mention.rs
@@ -1,24 +1,28 @@
 use crate::{
   newtypes::{CommentId, PersonId, PersonMentionId},
+  schema::person_mention::dsl::*,
   source::person_mention::*,
   traits::Crud,
+  utils::{get_conn, DbPool},
 };
 use diesel::{dsl::*, result::Error, *};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Crud for PersonMention {
   type InsertForm = PersonMentionInsertForm;
   type UpdateForm = PersonMentionUpdateForm;
   type IdType = PersonMentionId;
-  fn read(conn: &mut PgConnection, person_mention_id: PersonMentionId) -> Result<Self, Error> {
-    use crate::schema::person_mention::dsl::*;
-    person_mention.find(person_mention_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, person_mention_id: PersonMentionId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    person_mention
+      .find(person_mention_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(
-    conn: &mut PgConnection,
-    person_mention_form: &Self::InsertForm,
-  ) -> Result<Self, Error> {
-    use crate::schema::person_mention::dsl::*;
+  async fn create(pool: &DbPool, person_mention_form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     // since the return here isnt utilized, we dont need to do an update
     // but get_result doesnt return the existing row here
     insert_into(person_mention)
@@ -27,26 +31,28 @@ impl Crud for PersonMention {
       .do_update()
       .set(person_mention_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     person_mention_id: PersonMentionId,
     person_mention_form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::person_mention::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(person_mention.find(person_mention_id))
       .set(person_mention_form)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
 impl PersonMention {
-  pub fn mark_all_as_read(
-    conn: &mut PgConnection,
+  pub async fn mark_all_as_read(
+    pool: &DbPool,
     for_recipient_id: PersonId,
   ) -> Result<Vec<PersonMention>, Error> {
-    use crate::schema::person_mention::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(
       person_mention
         .filter(recipient_id.eq(for_recipient_id))
@@ -54,18 +60,20 @@ impl PersonMention {
     )
     .set(read.eq(true))
     .get_results::<Self>(conn)
+    .await
   }
 
-  pub fn read_by_comment_and_person(
-    conn: &mut PgConnection,
+  pub async fn read_by_comment_and_person(
+    pool: &DbPool,
     for_comment_id: CommentId,
     for_recipient_id: PersonId,
   ) -> Result<Self, Error> {
-    use crate::schema::person_mention::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     person_mention
       .filter(comment_id.eq(for_comment_id))
       .filter(recipient_id.eq(for_recipient_id))
       .first::<Self>(conn)
+      .await
   }
 }
 
@@ -81,16 +89,16 @@ mod tests {
       post::*,
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("terrylake".into())
@@ -98,7 +106,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let recipient_form = PersonInsertForm::builder()
       .name("terrylakes recipient".into())
@@ -106,7 +114,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_recipient = Person::create(conn, &recipient_form).unwrap();
+    let inserted_recipient = Person::create(pool, &recipient_form).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community lake".to_string())
@@ -115,7 +123,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -123,7 +131,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment".into())
@@ -131,7 +139,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     let person_mention_form = PersonMentionInsertForm {
       recipient_id: inserted_recipient.id,
@@ -139,7 +147,9 @@ mod tests {
       read: None,
     };
 
-    let inserted_mention = PersonMention::create(conn, &person_mention_form).unwrap();
+    let inserted_mention = PersonMention::create(pool, &person_mention_form)
+      .await
+      .unwrap();
 
     let expected_mention = PersonMention {
       id: inserted_mention.id,
@@ -149,17 +159,23 @@ mod tests {
       published: inserted_mention.published,
     };
 
-    let read_mention = PersonMention::read(conn, inserted_mention.id).unwrap();
+    let read_mention = PersonMention::read(pool, inserted_mention.id)
+      .await
+      .unwrap();
 
     let person_mention_update_form = PersonMentionUpdateForm { read: Some(false) };
     let updated_mention =
-      PersonMention::update(conn, inserted_mention.id, &person_mention_update_form).unwrap();
-    Comment::delete(conn, inserted_comment.id).unwrap();
-    Post::delete(conn, inserted_post.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Person::delete(conn, inserted_recipient.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+      PersonMention::update(pool, inserted_mention.id, &person_mention_update_form)
+        .await
+        .unwrap();
+    Comment::delete(pool, inserted_comment.id).await.unwrap();
+    Post::delete(pool, inserted_post.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Person::delete(pool, inserted_recipient.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_mention, read_mention);
     assert_eq!(expected_mention, inserted_mention);
diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs
index 95535b19..738e8a3b 100644
--- a/crates/db_schema/src/impls/post.rs
+++ b/crates/db_schema/src/impls/post.rs
@@ -1,5 +1,6 @@
 use crate::{
   newtypes::{CommunityId, DbUrl, PersonId, PostId},
+  schema::post::dsl::*,
   source::post::{
     Post,
     PostInsertForm,
@@ -12,53 +13,57 @@ use crate::{
     PostUpdateForm,
   },
   traits::{Crud, DeleteableOrRemoveable, Likeable, Readable, Saveable},
-  utils::{naive_now, FETCH_LIMIT_MAX},
+  utils::{get_conn, naive_now, DbPool, FETCH_LIMIT_MAX},
 };
-use diesel::{dsl::*, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl, *};
-use url::Url;
+use ::url::Url;
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl, TextExpressionMethods};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Crud for Post {
   type InsertForm = PostInsertForm;
   type UpdateForm = PostUpdateForm;
   type IdType = PostId;
-  fn read(conn: &mut PgConnection, post_id: PostId) -> Result<Self, Error> {
-    use crate::schema::post::dsl::*;
-    post.find(post_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, post_id: PostId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    post.find(post_id).first::<Self>(conn).await
   }
 
-  fn delete(conn: &mut PgConnection, post_id: PostId) -> Result<usize, Error> {
-    use crate::schema::post::dsl::*;
-    diesel::delete(post.find(post_id)).execute(conn)
+  async fn delete(pool: &DbPool, post_id: PostId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(post.find(post_id)).execute(conn).await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::post::dsl::*;
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(post)
       .values(form)
       .on_conflict(ap_id)
       .do_update()
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     post_id: PostId,
     new_post: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(post.find(post_id))
       .set(new_post)
       .get_result::<Self>(conn)
+      .await
   }
 }
 
 impl Post {
-  pub fn list_for_community(
-    conn: &mut PgConnection,
+  pub async fn list_for_community(
+    pool: &DbPool,
     the_community_id: CommunityId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     post
       .filter(community_id.eq(the_community_id))
       .filter(deleted.eq(false))
@@ -67,13 +72,14 @@ impl Post {
       .then_order_by(stickied.desc())
       .limit(FETCH_LIMIT_MAX)
       .load::<Self>(conn)
+      .await
   }
 
-  pub fn permadelete_for_creator(
-    conn: &mut PgConnection,
+  pub async fn permadelete_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
 
     let perma_deleted = "*Permananently Deleted*";
     let perma_deleted_url = "https://deleted.com";
@@ -87,15 +93,16 @@ impl Post {
         updated.eq(naive_now()),
       ))
       .get_results::<Self>(conn)
+      .await
   }
 
-  pub fn update_removed_for_creator(
-    conn: &mut PgConnection,
+  pub async fn update_removed_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
     for_community_id: Option<CommunityId>,
     new_removed: bool,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
 
     let mut update = diesel::update(post).into_boxed();
     update = update.filter(creator_id.eq(for_creator_id));
@@ -107,43 +114,47 @@ impl Post {
     update
       .set((removed.eq(new_removed), updated.eq(naive_now())))
       .get_results::<Self>(conn)
+      .await
   }
 
   pub fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool {
     person_id == post_creator_id
   }
 
-  pub fn read_from_apub_id(conn: &mut PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
-    use crate::schema::post::dsl::*;
+  pub async fn read_from_apub_id(pool: &DbPool, object_id: Url) -> Result<Option<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let object_id: DbUrl = object_id.into();
     Ok(
       post
         .filter(ap_id.eq(object_id))
         .first::<Post>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
   }
 
-  pub fn fetch_pictrs_posts_for_creator(
-    conn: &mut PgConnection,
+  pub async fn fetch_pictrs_posts_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
   ) -> Result<Vec<Self>, Error> {
     use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let pictrs_search = "%pictrs/image%";
 
     post
       .filter(creator_id.eq(for_creator_id))
       .filter(url.like(pictrs_search))
       .load::<Self>(conn)
+      .await
   }
 
   /// Sets the url and thumbnails fields to None
-  pub fn remove_pictrs_post_images_and_thumbnails_for_creator(
-    conn: &mut PgConnection,
+  pub async fn remove_pictrs_post_images_and_thumbnails_for_creator(
+    pool: &DbPool,
     for_creator_id: PersonId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let pictrs_search = "%pictrs/image%";
 
     diesel::update(
@@ -156,26 +167,28 @@ impl Post {
       thumbnail_url.eq::<Option<String>>(None),
     ))
     .get_results::<Self>(conn)
+    .await
   }
 
-  pub fn fetch_pictrs_posts_for_community(
-    conn: &mut PgConnection,
+  pub async fn fetch_pictrs_posts_for_community(
+    pool: &DbPool,
     for_community_id: CommunityId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let pictrs_search = "%pictrs/image%";
     post
       .filter(community_id.eq(for_community_id))
       .filter(url.like(pictrs_search))
       .load::<Self>(conn)
+      .await
   }
 
   /// Sets the url and thumbnails fields to None
-  pub fn remove_pictrs_post_images_and_thumbnails_for_community(
-    conn: &mut PgConnection,
+  pub async fn remove_pictrs_post_images_and_thumbnails_for_community(
+    pool: &DbPool,
     for_community_id: CommunityId,
   ) -> Result<Vec<Self>, Error> {
-    use crate::schema::post::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let pictrs_search = "%pictrs/image%";
 
     diesel::update(
@@ -188,77 +201,90 @@ impl Post {
       thumbnail_url.eq::<Option<String>>(None),
     ))
     .get_results::<Self>(conn)
+    .await
   }
 }
 
+#[async_trait]
 impl Likeable for PostLike {
   type Form = PostLikeForm;
   type IdType = PostId;
-  fn like(conn: &mut PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
+  async fn like(pool: &DbPool, post_like_form: &PostLikeForm) -> Result<Self, Error> {
     use crate::schema::post_like::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(post_like)
       .values(post_like_form)
       .on_conflict((post_id, person_id))
       .do_update()
       .set(post_like_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn remove(conn: &mut PgConnection, person_id: PersonId, post_id: PostId) -> Result<usize, Error> {
+  async fn remove(pool: &DbPool, person_id: PersonId, post_id: PostId) -> Result<usize, Error> {
     use crate::schema::post_like::dsl;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       dsl::post_like
         .filter(dsl::post_id.eq(post_id))
         .filter(dsl::person_id.eq(person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
+#[async_trait]
 impl Saveable for PostSaved {
   type Form = PostSavedForm;
-  fn save(conn: &mut PgConnection, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
+  async fn save(pool: &DbPool, post_saved_form: &PostSavedForm) -> Result<Self, Error> {
     use crate::schema::post_saved::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(post_saved)
       .values(post_saved_form)
       .on_conflict((post_id, person_id))
       .do_update()
       .set(post_saved_form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn unsave(conn: &mut PgConnection, post_saved_form: &PostSavedForm) -> Result<usize, Error> {
+  async fn unsave(pool: &DbPool, post_saved_form: &PostSavedForm) -> Result<usize, Error> {
     use crate::schema::post_saved::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       post_saved
         .filter(post_id.eq(post_saved_form.post_id))
         .filter(person_id.eq(post_saved_form.person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
+#[async_trait]
 impl Readable for PostRead {
   type Form = PostReadForm;
-  fn mark_as_read(conn: &mut PgConnection, post_read_form: &PostReadForm) -> Result<Self, Error> {
+  async fn mark_as_read(pool: &DbPool, post_read_form: &PostReadForm) -> Result<Self, Error> {
     use crate::schema::post_read::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     insert_into(post_read)
       .values(post_read_form)
       .on_conflict((post_id, person_id))
       .do_update()
       .set(post_read_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn mark_as_unread(
-    conn: &mut PgConnection,
-    post_read_form: &PostReadForm,
-  ) -> Result<usize, Error> {
+  async fn mark_as_unread(pool: &DbPool, post_read_form: &PostReadForm) -> Result<usize, Error> {
     use crate::schema::post_read::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::delete(
       post_read
         .filter(post_id.eq(post_read_form.post_id))
         .filter(person_id.eq(post_read_form.person_id)),
     )
     .execute(conn)
+    .await
   }
 }
 
@@ -286,16 +312,16 @@ mod tests {
       post::*,
     },
     traits::{Crud, Likeable, Readable, Saveable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("jim".into())
@@ -303,7 +329,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community_3".to_string())
@@ -312,7 +338,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post".into())
@@ -320,7 +346,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let expected_post = Post {
       id: inserted_post.id,
@@ -352,7 +378,7 @@ mod tests {
       score: 1,
     };
 
-    let inserted_post_like = PostLike::like(conn, &post_like_form).unwrap();
+    let inserted_post_like = PostLike::like(pool, &post_like_form).await.unwrap();
 
     let expected_post_like = PostLike {
       id: inserted_post_like.id,
@@ -368,7 +394,7 @@ mod tests {
       person_id: inserted_person.id,
     };
 
-    let inserted_post_saved = PostSaved::save(conn, &post_saved_form).unwrap();
+    let inserted_post_saved = PostSaved::save(pool, &post_saved_form).await.unwrap();
 
     let expected_post_saved = PostSaved {
       id: inserted_post_saved.id,
@@ -383,7 +409,7 @@ mod tests {
       person_id: inserted_person.id,
     };
 
-    let inserted_post_read = PostRead::mark_as_read(conn, &post_read_form).unwrap();
+    let inserted_post_read = PostRead::mark_as_read(pool, &post_read_form).await.unwrap();
 
     let expected_post_read = PostRead {
       id: inserted_post_read.id,
@@ -392,20 +418,28 @@ mod tests {
       published: inserted_post_read.published,
     };
 
-    let read_post = Post::read(conn, inserted_post.id).unwrap();
+    let read_post = Post::read(pool, inserted_post.id).await.unwrap();
 
     let new_post_update = PostUpdateForm::builder()
       .name(Some("A test post".into()))
       .build();
-    let updated_post = Post::update(conn, inserted_post.id, &new_post_update).unwrap();
-
-    let like_removed = PostLike::remove(conn, inserted_person.id, inserted_post.id).unwrap();
-    let saved_removed = PostSaved::unsave(conn, &post_saved_form).unwrap();
-    let read_removed = PostRead::mark_as_unread(conn, &post_read_form).unwrap();
-    let num_deleted = Post::delete(conn, inserted_post.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Person::delete(conn, inserted_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    let updated_post = Post::update(pool, inserted_post.id, &new_post_update)
+      .await
+      .unwrap();
+
+    let like_removed = PostLike::remove(pool, inserted_person.id, inserted_post.id)
+      .await
+      .unwrap();
+    let saved_removed = PostSaved::unsave(pool, &post_saved_form).await.unwrap();
+    let read_removed = PostRead::mark_as_unread(pool, &post_read_form)
+      .await
+      .unwrap();
+    let num_deleted = Post::delete(pool, inserted_post.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_post, read_post);
     assert_eq!(expected_post, inserted_post);
diff --git a/crates/db_schema/src/impls/post_report.rs b/crates/db_schema/src/impls/post_report.rs
index f9a1eab2..07e58a88 100644
--- a/crates/db_schema/src/impls/post_report.rs
+++ b/crates/db_schema/src/impls/post_report.rs
@@ -1,37 +1,32 @@
 use crate::{
   newtypes::{PersonId, PostReportId},
+  schema::post_report::dsl::*,
   source::post_report::*,
   traits::Reportable,
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Reportable for PostReport {
   type Form = PostReportForm;
   type IdType = PostReportId;
 
-  /// creates a post report and returns it
-  ///
-  /// * `conn` - the postgres connection
-  /// * `post_report_form` - the filled CommentReportForm to insert
-  fn report(conn: &mut PgConnection, post_report_form: &PostReportForm) -> Result<Self, Error> {
-    use crate::schema::post_report::dsl::*;
+  async fn report(pool: &DbPool, post_report_form: &PostReportForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(post_report)
       .values(post_report_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  /// resolve a post report
-  ///
-  /// * `conn` - the postgres connection
-  /// * `report_id` - the id of the report to resolve
-  /// * `by_resolver_id` - the id of the user resolving the report
-  fn resolve(
-    conn: &mut PgConnection,
+  async fn resolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::post_report::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     update(post_report.find(report_id))
       .set((
         resolved.eq(true),
@@ -39,19 +34,15 @@ impl Reportable for PostReport {
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 
-  /// resolve a post report
-  ///
-  /// * `conn` - the postgres connection
-  /// * `report_id` - the id of the report to unresolve
-  /// * `by_resolver_id` - the id of the user unresolving the report
-  fn unresolve(
-    conn: &mut PgConnection,
+  async fn unresolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::post_report::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     update(post_report.find(report_id))
       .set((
         resolved.eq(false),
@@ -59,5 +50,6 @@ impl Reportable for PostReport {
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/private_message.rs b/crates/db_schema/src/impls/private_message.rs
index 80818ee3..0e5a5031 100644
--- a/crates/db_schema/src/impls/private_message.rs
+++ b/crates/db_schema/src/impls/private_message.rs
@@ -1,53 +1,64 @@
 use crate::{
   newtypes::{DbUrl, PersonId, PrivateMessageId},
+  schema::private_message::dsl::*,
   source::private_message::*,
   traits::{Crud, DeleteableOrRemoveable},
+  utils::{get_conn, DbPool},
 };
 use diesel::{dsl::*, result::Error, *};
+use diesel_async::RunQueryDsl;
 use lemmy_utils::error::LemmyError;
 use url::Url;
 
+#[async_trait]
 impl Crud for PrivateMessage {
   type InsertForm = PrivateMessageInsertForm;
   type UpdateForm = PrivateMessageUpdateForm;
   type IdType = PrivateMessageId;
-  fn read(conn: &mut PgConnection, private_message_id: PrivateMessageId) -> Result<Self, Error> {
-    use crate::schema::private_message::dsl::*;
-    private_message.find(private_message_id).first::<Self>(conn)
+  async fn read(pool: &DbPool, private_message_id: PrivateMessageId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    private_message
+      .find(private_message_id)
+      .first::<Self>(conn)
+      .await
   }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::private_message::dsl::*;
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(private_message)
       .values(form)
       .on_conflict(ap_id)
       .do_update()
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     private_message_id: PrivateMessageId,
     form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::private_message::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(private_message.find(private_message_id))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
-  fn delete(conn: &mut PgConnection, pm_id: Self::IdType) -> Result<usize, Error> {
-    use crate::schema::private_message::dsl::*;
-    diesel::delete(private_message.find(pm_id)).execute(conn)
+  async fn delete(pool: &DbPool, pm_id: Self::IdType) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(private_message.find(pm_id))
+      .execute(conn)
+      .await
   }
 }
 
 impl PrivateMessage {
-  pub fn mark_all_as_read(
-    conn: &mut PgConnection,
+  pub async fn mark_all_as_read(
+    pool: &DbPool,
     for_recipient_id: PersonId,
   ) -> Result<Vec<PrivateMessage>, Error> {
-    use crate::schema::private_message::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(
       private_message
         .filter(recipient_id.eq(for_recipient_id))
@@ -55,18 +66,20 @@ impl PrivateMessage {
     )
     .set(read.eq(true))
     .get_results::<Self>(conn)
+    .await
   }
 
-  pub fn read_from_apub_id(
-    conn: &mut PgConnection,
+  pub async fn read_from_apub_id(
+    pool: &DbPool,
     object_id: Url,
   ) -> Result<Option<Self>, LemmyError> {
-    use crate::schema::private_message::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let object_id: DbUrl = object_id.into();
     Ok(
       private_message
         .filter(ap_id.eq(object_id))
         .first::<PrivateMessage>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
@@ -85,16 +98,16 @@ mod tests {
   use crate::{
     source::{instance::Instance, person::*, private_message::*},
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let creator_form = PersonInsertForm::builder()
       .name("creator_pm".into())
@@ -102,7 +115,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_creator = Person::create(conn, &creator_form).unwrap();
+    let inserted_creator = Person::create(pool, &creator_form).await.unwrap();
 
     let recipient_form = PersonInsertForm::builder()
       .name("recipient_pm".into())
@@ -110,7 +123,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_recipient = Person::create(conn, &recipient_form).unwrap();
+    let inserted_recipient = Person::create(pool, &recipient_form).await.unwrap();
 
     let private_message_form = PrivateMessageInsertForm::builder()
       .content("A test private message".into())
@@ -118,7 +131,9 @@ mod tests {
       .recipient_id(inserted_recipient.id)
       .build();
 
-    let inserted_private_message = PrivateMessage::create(conn, &private_message_form).unwrap();
+    let inserted_private_message = PrivateMessage::create(pool, &private_message_form)
+      .await
+      .unwrap();
 
     let expected_private_message = PrivateMessage {
       id: inserted_private_message.id,
@@ -133,35 +148,40 @@ mod tests {
       local: true,
     };
 
-    let read_private_message = PrivateMessage::read(conn, inserted_private_message.id).unwrap();
+    let read_private_message = PrivateMessage::read(pool, inserted_private_message.id)
+      .await
+      .unwrap();
 
     let private_message_update_form = PrivateMessageUpdateForm::builder()
       .content(Some("A test private message".into()))
       .build();
     let updated_private_message = PrivateMessage::update(
-      conn,
+      pool,
       inserted_private_message.id,
       &private_message_update_form,
     )
+    .await
     .unwrap();
 
     let deleted_private_message = PrivateMessage::update(
-      conn,
+      pool,
       inserted_private_message.id,
       &PrivateMessageUpdateForm::builder()
         .deleted(Some(true))
         .build(),
     )
+    .await
     .unwrap();
     let marked_read_private_message = PrivateMessage::update(
-      conn,
+      pool,
       inserted_private_message.id,
       &PrivateMessageUpdateForm::builder().read(Some(true)).build(),
     )
+    .await
     .unwrap();
-    Person::delete(conn, inserted_creator.id).unwrap();
-    Person::delete(conn, inserted_recipient.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Person::delete(pool, inserted_creator.id).await.unwrap();
+    Person::delete(pool, inserted_recipient.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
 
     assert_eq!(expected_private_message, read_private_message);
     assert_eq!(expected_private_message, updated_private_message);
diff --git a/crates/db_schema/src/impls/private_message_report.rs b/crates/db_schema/src/impls/private_message_report.rs
index 08fe4d28..70af3615 100644
--- a/crates/db_schema/src/impls/private_message_report.rs
+++ b/crates/db_schema/src/impls/private_message_report.rs
@@ -1,39 +1,32 @@
 use crate::{
   newtypes::{PersonId, PrivateMessageReportId},
+  schema::private_message_report::dsl::*,
   source::private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
   traits::Reportable,
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
 use diesel::{dsl::*, result::Error, *};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Reportable for PrivateMessageReport {
   type Form = PrivateMessageReportForm;
   type IdType = PrivateMessageReportId;
-  /// creates a comment report and returns it
-  ///
-  /// * `conn` - the postgres connection
-  /// * `comment_report_form` - the filled CommentReportForm to insert
-  fn report(
-    conn: &mut PgConnection,
-    pm_report_form: &PrivateMessageReportForm,
-  ) -> Result<Self, Error> {
-    use crate::schema::private_message_report::dsl::*;
+
+  async fn report(pool: &DbPool, pm_report_form: &PrivateMessageReportForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(private_message_report)
       .values(pm_report_form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  /// resolve a pm report
-  ///
-  /// * `conn` - the postgres connection
-  /// * `report_id` - the id of the report to resolve
-  /// * `by_resolver_id` - the id of the user resolving the report
-  fn resolve(
-    conn: &mut PgConnection,
+  async fn resolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::private_message_report::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     update(private_message_report.find(report_id))
       .set((
         resolved.eq(true),
@@ -41,19 +34,15 @@ impl Reportable for PrivateMessageReport {
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 
-  /// unresolve a comment report
-  ///
-  /// * `conn` - the postgres connection
-  /// * `report_id` - the id of the report to unresolve
-  /// * `by_resolver_id` - the id of the user unresolving the report
-  fn unresolve(
-    conn: &mut PgConnection,
+  async fn unresolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     by_resolver_id: PersonId,
   ) -> Result<usize, Error> {
-    use crate::schema::private_message_report::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     update(private_message_report.find(report_id))
       .set((
         resolved.eq(false),
@@ -61,5 +50,6 @@ impl Reportable for PrivateMessageReport {
         updated.eq(naive_now()),
       ))
       .execute(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/registration_application.rs b/crates/db_schema/src/impls/registration_application.rs
index 8004abc6..72daf4eb 100644
--- a/crates/db_schema/src/impls/registration_application.rs
+++ b/crates/db_schema/src/impls/registration_application.rs
@@ -1,47 +1,61 @@
-use crate::{newtypes::LocalUserId, source::registration_application::*, traits::Crud};
-use diesel::{insert_into, result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
+use crate::{
+  newtypes::LocalUserId,
+  schema::registration_application::dsl::*,
+  source::registration_application::*,
+  traits::Crud,
+  utils::{get_conn, DbPool},
+};
+use diesel::{insert_into, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 
+#[async_trait]
 impl Crud for RegistrationApplication {
   type InsertForm = RegistrationApplicationInsertForm;
   type UpdateForm = RegistrationApplicationUpdateForm;
   type IdType = i32;
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::registration_application::dsl::*;
+
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     insert_into(registration_application)
       .values(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn read(conn: &mut PgConnection, id_: Self::IdType) -> Result<Self, Error> {
-    use crate::schema::registration_application::dsl::*;
-    registration_application.find(id_).first::<Self>(conn)
+  async fn read(pool: &DbPool, id_: Self::IdType) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    registration_application.find(id_).first::<Self>(conn).await
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     id_: Self::IdType,
     form: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::registration_application::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(registration_application.find(id_))
       .set(form)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn delete(conn: &mut PgConnection, id_: Self::IdType) -> Result<usize, Error> {
-    use crate::schema::registration_application::dsl::*;
-    diesel::delete(registration_application.find(id_)).execute(conn)
+  async fn delete(pool: &DbPool, id_: Self::IdType) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(registration_application.find(id_))
+      .execute(conn)
+      .await
   }
 }
 
 impl RegistrationApplication {
-  pub fn find_by_local_user_id(
-    conn: &mut PgConnection,
+  pub async fn find_by_local_user_id(
+    pool: &DbPool,
     local_user_id_: LocalUserId,
   ) -> Result<Self, Error> {
-    use crate::schema::registration_application::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     registration_application
       .filter(local_user_id.eq(local_user_id_))
       .first::<Self>(conn)
+      .await
   }
 }
diff --git a/crates/db_schema/src/impls/secret.rs b/crates/db_schema/src/impls/secret.rs
index 1f92ee24..0c005c09 100644
--- a/crates/db_schema/src/impls/secret.rs
+++ b/crates/db_schema/src/impls/secret.rs
@@ -1,15 +1,20 @@
-use crate::source::secret::Secret;
-use diesel::{result::Error, *};
+use crate::{
+  schema::secret::dsl::*,
+  source::secret::Secret,
+  utils::{get_conn, DbPool},
+};
+use diesel::result::Error;
+use diesel_async::RunQueryDsl;
 
 impl Secret {
   /// Initialize the Secrets from the DB.
   /// Warning: You should only call this once.
-  pub fn init(conn: &mut PgConnection) -> Result<Secret, Error> {
-    read_secrets(conn)
+  pub async fn init(pool: &DbPool) -> Result<Secret, Error> {
+    Self::read_secrets(pool).await
   }
-}
 
-fn read_secrets(conn: &mut PgConnection) -> Result<Secret, Error> {
-  use crate::schema::secret::dsl::*;
-  secret.first::<Secret>(conn)
+  async fn read_secrets(pool: &DbPool) -> Result<Secret, Error> {
+    let conn = &mut get_conn(pool).await?;
+    secret.first::<Secret>(conn).await
+  }
 }
diff --git a/crates/db_schema/src/impls/site.rs b/crates/db_schema/src/impls/site.rs
index de53c19d..0588f008 100644
--- a/crates/db_schema/src/impls/site.rs
+++ b/crates/db_schema/src/impls/site.rs
@@ -1,68 +1,75 @@
 use crate::{
   newtypes::{DbUrl, SiteId},
+  schema::site::dsl::*,
   source::{actor_language::SiteLanguage, site::*},
   traits::Crud,
+  utils::{get_conn, DbPool},
 };
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use url::Url;
 
+#[async_trait]
 impl Crud for Site {
   type InsertForm = SiteInsertForm;
   type UpdateForm = SiteUpdateForm;
   type IdType = SiteId;
-  fn read(conn: &mut PgConnection, _site_id: SiteId) -> Result<Self, Error> {
-    use crate::schema::site::dsl::*;
-    site.first::<Self>(conn)
-  }
 
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error> {
-    use crate::schema::site::dsl::*;
+  async fn read(pool: &DbPool, _site_id: SiteId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+    site.first::<Self>(conn).await
+  }
 
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let site_ = insert_into(site)
       .values(form)
       .on_conflict(actor_id)
       .do_update()
       .set(form)
-      .get_result::<Self>(conn)?;
+      .get_result::<Self>(conn)
+      .await?;
 
     // initialize with all languages
-    SiteLanguage::update(conn, vec![], &site_)?;
+    SiteLanguage::update(pool, vec![], &site_).await?;
     Ok(site_)
   }
 
-  fn update(
-    conn: &mut PgConnection,
+  async fn update(
+    pool: &DbPool,
     site_id: SiteId,
     new_site: &Self::UpdateForm,
   ) -> Result<Self, Error> {
-    use crate::schema::site::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     diesel::update(site.find(site_id))
       .set(new_site)
       .get_result::<Self>(conn)
+      .await
   }
 
-  fn delete(conn: &mut PgConnection, site_id: SiteId) -> Result<usize, Error> {
-    use crate::schema::site::dsl::*;
-    diesel::delete(site.find(site_id)).execute(conn)
+  async fn delete(pool: &DbPool, site_id: SiteId) -> Result<usize, Error> {
+    let conn = &mut get_conn(pool).await?;
+    diesel::delete(site.find(site_id)).execute(conn).await
   }
 }
 
 impl Site {
-  pub fn read_from_apub_id(conn: &mut PgConnection, object_id: Url) -> Result<Option<Self>, Error> {
-    use crate::schema::site::dsl::*;
+  pub async fn read_from_apub_id(pool: &DbPool, object_id: Url) -> Result<Option<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let object_id: DbUrl = object_id.into();
     Ok(
       site
         .filter(actor_id.eq(object_id))
         .first::<Site>(conn)
+        .await
         .ok()
         .map(Into::into),
     )
   }
 
   // TODO this needs fixed
-  pub fn read_remote_sites(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
-    use crate::schema::site::dsl::*;
-    site.order_by(id).offset(1).get_results::<Self>(conn)
+  pub async fn read_remote_sites(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+    site.order_by(id).offset(1).get_results::<Self>(conn).await
   }
 }
diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs
index a859b2aa..43b31c91 100644
--- a/crates/db_schema/src/lib.rs
+++ b/crates/db_schema/src/lib.rs
@@ -12,6 +12,9 @@ extern crate diesel_derive_newtype;
 #[macro_use]
 extern crate diesel_migrations;
 
+#[macro_use]
+extern crate async_trait;
+
 pub mod aggregates;
 #[cfg(feature = "full")]
 pub mod impls;
diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs
index 6e6d2c70..75cfcd50 100644
--- a/crates/db_schema/src/traits.rs
+++ b/crates/db_schema/src/traits.rs
@@ -1,69 +1,72 @@
-use crate::newtypes::{CommunityId, DbUrl, PersonId};
-use diesel::{result::Error, PgConnection};
+use crate::{
+  newtypes::{CommunityId, DbUrl, PersonId},
+  utils::DbPool,
+};
+use diesel::result::Error;
 
+#[async_trait]
 pub trait Crud {
   type InsertForm;
   type UpdateForm;
   type IdType;
-  fn create(conn: &mut PgConnection, form: &Self::InsertForm) -> Result<Self, Error>
+  async fn create(pool: &DbPool, form: &Self::InsertForm) -> Result<Self, Error>
   where
     Self: Sized;
-  fn read(conn: &mut PgConnection, id: Self::IdType) -> Result<Self, Error>
+  async fn read(pool: &DbPool, id: Self::IdType) -> Result<Self, Error>
   where
     Self: Sized;
   /// when you want to null out a column, you have to send Some(None)), since sending None means you just don't want to update that column.
-  fn update(
-    conn: &mut PgConnection,
-    id: Self::IdType,
-    form: &Self::UpdateForm,
-  ) -> Result<Self, Error>
+  async fn update(pool: &DbPool, id: Self::IdType, form: &Self::UpdateForm) -> Result<Self, Error>
   where
     Self: Sized;
-  fn delete(_conn: &mut PgConnection, _id: Self::IdType) -> Result<usize, Error>
+  async fn delete(_pool: &DbPool, _id: Self::IdType) -> Result<usize, Error>
   where
     Self: Sized,
+    Self::IdType: Send,
   {
-    unimplemented!()
+    async { Err(Error::NotFound) }.await
   }
 }
 
+#[async_trait]
 pub trait Followable {
   type Form;
-  fn follow(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn follow(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn follow_accepted(
-    conn: &mut PgConnection,
+  async fn follow_accepted(
+    pool: &DbPool,
     community_id: CommunityId,
     person_id: PersonId,
   ) -> Result<Self, Error>
   where
     Self: Sized;
-  fn unfollow(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn unfollow(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
-  fn has_local_followers(conn: &mut PgConnection, community_id: CommunityId)
-    -> Result<bool, Error>;
+  async fn has_local_followers(pool: &DbPool, community_id: CommunityId) -> Result<bool, Error>;
 }
 
+#[async_trait]
 pub trait Joinable {
   type Form;
-  fn join(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn join(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn leave(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn leave(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Likeable {
   type Form;
   type IdType;
-  fn like(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn like(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn remove(
-    conn: &mut PgConnection,
+  async fn remove(
+    pool: &DbPool,
     person_id: PersonId,
     item_id: Self::IdType,
   ) -> Result<usize, Error>
@@ -71,61 +74,66 @@ pub trait Likeable {
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Bannable {
   type Form;
-  fn ban(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn ban(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn unban(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn unban(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Saveable {
   type Form;
-  fn save(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn save(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn unsave(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn unsave(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Blockable {
   type Form;
-  fn block(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn block(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn unblock(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn unblock(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Readable {
   type Form;
-  fn mark_as_read(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn mark_as_read(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn mark_as_unread(conn: &mut PgConnection, form: &Self::Form) -> Result<usize, Error>
+  async fn mark_as_unread(pool: &DbPool, form: &Self::Form) -> Result<usize, Error>
   where
     Self: Sized;
 }
 
+#[async_trait]
 pub trait Reportable {
   type Form;
   type IdType;
-  fn report(conn: &mut PgConnection, form: &Self::Form) -> Result<Self, Error>
+  async fn report(pool: &DbPool, form: &Self::Form) -> Result<Self, Error>
   where
     Self: Sized;
-  fn resolve(
-    conn: &mut PgConnection,
+  async fn resolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     resolver_id: PersonId,
   ) -> Result<usize, Error>
   where
     Self: Sized;
-  fn unresolve(
-    conn: &mut PgConnection,
+  async fn unresolve(
+    pool: &DbPool,
     report_id: Self::IdType,
     resolver_id: PersonId,
   ) -> Result<usize, Error>
@@ -133,6 +141,7 @@ pub trait Reportable {
     Self: Sized;
 }
 
+// TODO these should be removed, there should be another way to do this
 pub trait DeleteableOrRemoveable {
   fn blank_out_deleted_or_removed_info(self) -> Self;
 }
@@ -154,22 +163,23 @@ pub trait ViewToVec {
     Self: Sized;
 }
 
+#[async_trait]
 pub trait ApubActor {
   // TODO: this should be in a trait ApubObject (and implemented for Post, Comment, PrivateMessage as well)
-  fn read_from_apub_id(conn: &mut PgConnection, object_id: &DbUrl) -> Result<Option<Self>, Error>
+  async fn read_from_apub_id(pool: &DbPool, object_id: &DbUrl) -> Result<Option<Self>, Error>
   where
     Self: Sized;
   /// - actor_name is the name of the community or user to read.
   /// - include_deleted, if true, will return communities or users that were deleted/removed
-  fn read_from_name(
-    conn: &mut PgConnection,
+  async fn read_from_name(
+    pool: &DbPool,
     actor_name: &str,
     include_deleted: bool,
   ) -> Result<Self, Error>
   where
     Self: Sized;
-  fn read_from_name_and_domain(
-    conn: &mut PgConnection,
+  async fn read_from_name_and_domain(
+    pool: &DbPool,
     actor_name: &str,
     protocol_domain: &str,
   ) -> Result<Self, Error>
diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs
index d20b32d8..f8a6f7db 100644
--- a/crates/db_schema/src/utils.rs
+++ b/crates/db_schema/src/utils.rs
@@ -1,18 +1,28 @@
-use crate::{diesel_migrations::MigrationHarness, newtypes::DbUrl, CommentSortType, SortType};
+use crate::{
+  diesel::Connection,
+  diesel_migrations::MigrationHarness,
+  newtypes::DbUrl,
+  CommentSortType,
+  SortType,
+};
 use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
+use bb8::PooledConnection;
 use chrono::NaiveDateTime;
 use diesel::{
   backend::Backend,
   deserialize::FromSql,
   pg::Pg,
-  result::Error::QueryBuilderError,
+  result::{Error as DieselError, Error::QueryBuilderError},
   serialize::{Output, ToSql},
   sql_types::Text,
-  Connection,
   PgConnection,
 };
+use diesel_async::{
+  pg::AsyncPgConnection,
+  pooled_connection::{bb8::Pool, AsyncDieselConnectionManager},
+};
 use diesel_migrations::EmbeddedMigrations;
-use lemmy_utils::error::LemmyError;
+use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use once_cell::sync::Lazy;
 use regex::Regex;
 use std::{env, env::VarError};
@@ -21,7 +31,14 @@ use url::Url;
 const FETCH_LIMIT_DEFAULT: i64 = 10;
 pub const FETCH_LIMIT_MAX: i64 = 50;
 
-pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
+pub type DbPool = Pool<AsyncPgConnection>;
+
+pub async fn get_conn(
+  pool: &DbPool,
+) -> Result<PooledConnection<AsyncDieselConnectionManager<AsyncPgConnection>>, DieselError> {
+  // TODO Maybe find a better diesel error for this
+  pool.get().await.map_err(|_| DieselError::NotInTransaction)
+}
 
 pub fn get_database_url_from_env() -> Result<String, VarError> {
   env::var("LEMMY_DATABASE_URL")
@@ -114,22 +131,57 @@ pub fn diesel_option_overwrite_to_url_create(
   }
 }
 
+async fn build_db_pool_settings_opt(settings: Option<&Settings>) -> Result<DbPool, LemmyError> {
+  let db_url = get_database_url(settings);
+  let pool_size = settings.map(|s| s.database.pool_size).unwrap_or(5);
+  let manager = AsyncDieselConnectionManager::<AsyncPgConnection>::new(&db_url);
+  let pool = Pool::builder()
+    .max_size(pool_size)
+    .min_idle(Some(1))
+    .build(manager)
+    .await?;
+
+  // If there's no settings, that means its a unit test, and migrations need to be run
+  if settings.is_none() {
+    run_migrations(&db_url);
+  }
+
+  Ok(pool)
+}
+
 pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
 
-pub fn establish_unpooled_connection() -> PgConnection {
-  let db_url = match get_database_url_from_env() {
-    Ok(url) => url,
-    Err(e) => panic!(
-      "Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
-      e
-    ),
-  };
+pub fn run_migrations(db_url: &str) {
+  // Needs to be a sync connection
   let mut conn =
-    PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
+    PgConnection::establish(db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
   let _ = &mut conn
     .run_pending_migrations(MIGRATIONS)
     .unwrap_or_else(|_| panic!("Couldn't run DB Migrations"));
-  conn
+}
+
+pub async fn build_db_pool(settings: &Settings) -> Result<DbPool, LemmyError> {
+  build_db_pool_settings_opt(Some(settings)).await
+}
+
+pub async fn build_db_pool_for_tests() -> DbPool {
+  build_db_pool_settings_opt(None)
+    .await
+    .expect("db pool missing")
+}
+
+pub fn get_database_url(settings: Option<&Settings>) -> String {
+  // The env var should override anything in the settings config
+  match get_database_url_from_env() {
+    Ok(url) => url,
+    Err(e) => match settings {
+      Some(settings) => settings.get_database_url(),
+      None => panic!(
+        "Failed to read database URL from env var LEMMY_DATABASE_URL: {}",
+        e
+      ),
+    },
+  }
 }
 
 pub fn naive_now() -> NaiveDateTime {
diff --git a/crates/db_views/Cargo.toml b/crates/db_views/Cargo.toml
index 1a9e31eb..c454c282 100644
--- a/crates/db_views/Cargo.toml
+++ b/crates/db_views/Cargo.toml
@@ -12,16 +12,18 @@ rust-version = "1.57"
 doctest = false
 
 [features]
-full = ["lemmy_db_schema/full", "diesel", "tracing"]
+full = ["lemmy_db_schema/full", "diesel", "diesel-async", "diesel_ltree", "tracing"]
 
 [dependencies]
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
-diesel = { version = "2.0.0", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
-serde = { version = "1.0.145", features = ["derive"] }
+diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
+diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true}
+diesel_ltree = { version = "0.3.0", optional = true}
+serde = { version = "1.0.147", features = ["derive"] }
 tracing = { version = "0.1.36", optional = true }
-diesel_ltree = "0.3.0"
 typed-builder = "0.10.0"
 url = { version = "2.3.1", features = ["serde"] }
 
 [dev-dependencies]
 serial_test = "0.9.0"
+tokio = "1.21.2"
diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs
index e4a6a493..75aed926 100644
--- a/crates/db_views/src/comment_report_view.rs
+++ b/crates/db_views/src/comment_report_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::CommentReportView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::CommentAggregates,
   newtypes::{CommentReportId, CommunityId, PersonId},
@@ -22,7 +31,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 use typed_builder::TypedBuilder;
 
@@ -43,11 +52,13 @@ impl CommentReportView {
   /// returns the CommentReportView for the provided report_id
   ///
   /// * `report_id` - the report id to obtain
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     report_id: CommentReportId,
     my_person_id: PersonId,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let (
@@ -108,7 +119,8 @@ impl CommentReportView {
           .fields(Person::safe_columns_tuple())
           .nullable(),
       ))
-      .first::<CommentReportViewTuple>(conn)?;
+      .first::<CommentReportViewTuple>(conn)
+      .await?;
 
     let my_vote = comment_like;
 
@@ -127,14 +139,16 @@ impl CommentReportView {
   }
 
   /// Returns the current unresolved post report count for the communities you mod
-  pub fn get_report_count(
-    conn: &mut PgConnection,
+  pub async fn get_report_count(
+    pool: &DbPool,
     my_person_id: PersonId,
     admin: bool,
     community_id: Option<CommunityId>,
   ) -> Result<i64, Error> {
     use diesel::dsl::*;
 
+    let conn = &mut get_conn(pool).await?;
+
     let mut query = comment_report::table
       .inner_join(comment::table)
       .inner_join(post::table.on(comment::post_id.eq(post::id)))
@@ -157,8 +171,12 @@ impl CommentReportView {
         )
         .select(count(comment_report::id))
         .first::<i64>(conn)
+        .await
     } else {
-      query.select(count(comment_report::id)).first::<i64>(conn)
+      query
+        .select(count(comment_report::id))
+        .first::<i64>(conn)
+        .await
     }
   }
 }
@@ -167,7 +185,7 @@ impl CommentReportView {
 #[builder(field_defaults(default))]
 pub struct CommentReportQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   #[builder(!default)]
   my_person_id: PersonId,
   #[builder(!default)]
@@ -179,7 +197,9 @@ pub struct CommentReportQuery<'a> {
 }
 
 impl<'a> CommentReportQuery<'a> {
-  pub fn list(self) -> Result<Vec<CommentReportView>, Error> {
+  pub async fn list(self) -> Result<Vec<CommentReportView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
+
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let mut query = comment_report::table
@@ -255,9 +275,10 @@ impl<'a> CommentReportQuery<'a> {
               .and(community_moderator::person_id.eq(self.my_person_id)),
           ),
         )
-        .load::<CommentReportViewTuple>(self.conn)?
+        .load::<CommentReportViewTuple>(conn)
+        .await?
     } else {
-      query.load::<CommentReportViewTuple>(self.conn)?
+      query.load::<CommentReportViewTuple>(conn).await?
     };
 
     Ok(CommentReportView::from_tuple_to_vec(res))
@@ -292,16 +313,16 @@ mod tests {
     aggregates::structs::CommentAggregates,
     source::{comment::*, comment_report::*, community::*, instance::Instance, person::*, post::*},
     traits::{Crud, Joinable, Reportable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("timmy_crv".into())
@@ -309,7 +330,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_timmy = Person::create(conn, &new_person).unwrap();
+    let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
 
     let new_person_2 = PersonInsertForm::builder()
       .name("sara_crv".into())
@@ -317,7 +338,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_sara = Person::create(conn, &new_person_2).unwrap();
+    let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
 
     // Add a third person, since new ppl can only report something once.
     let new_person_3 = PersonInsertForm::builder()
@@ -326,7 +347,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
+    let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community crv".to_string())
@@ -335,7 +356,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     // Make timmy a mod
     let timmy_moderator_form = CommunityModeratorForm {
@@ -343,7 +364,9 @@ mod tests {
       person_id: inserted_timmy.id,
     };
 
-    let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
+    let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
+      .await
+      .unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post crv".into())
@@ -351,7 +374,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let comment_form = CommentInsertForm::builder()
       .content("A test comment 32".into())
@@ -359,7 +382,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment = Comment::create(conn, &comment_form, None).unwrap();
+    let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
 
     // sara reports
     let sara_report_form = CommentReportForm {
@@ -369,7 +392,9 @@ mod tests {
       reason: "from sara".into(),
     };
 
-    let inserted_sara_report = CommentReport::report(conn, &sara_report_form).unwrap();
+    let inserted_sara_report = CommentReport::report(pool, &sara_report_form)
+      .await
+      .unwrap();
 
     // jessica reports
     let jessica_report_form = CommentReportForm {
@@ -379,12 +404,18 @@ mod tests {
       reason: "from jessica".into(),
     };
 
-    let inserted_jessica_report = CommentReport::report(conn, &jessica_report_form).unwrap();
+    let inserted_jessica_report = CommentReport::report(pool, &jessica_report_form)
+      .await
+      .unwrap();
 
-    let agg = CommentAggregates::read(conn, inserted_comment.id).unwrap();
+    let agg = CommentAggregates::read(pool, inserted_comment.id)
+      .await
+      .unwrap();
 
     let read_jessica_report_view =
-      CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+      CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
+        .await
+        .unwrap();
     let expected_jessica_report_view = CommentReportView {
       comment_report: inserted_jessica_report.to_owned(),
       comment: inserted_comment.to_owned(),
@@ -491,11 +522,12 @@ mod tests {
 
     // Do a batch read of timmys reports
     let reports = CommentReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .my_person_id(inserted_timmy.id)
       .admin(false)
       .build()
       .list()
+      .await
       .unwrap();
 
     assert_eq!(
@@ -507,14 +539,19 @@ mod tests {
     );
 
     // Make sure the counts are correct
-    let report_count =
-      CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
+    let report_count = CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
+      .await
+      .unwrap();
     assert_eq!(2, report_count);
 
     // Try to resolve the report
-    CommentReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+    CommentReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
+      .await
+      .unwrap();
     let read_jessica_report_view_after_resolve =
-      CommentReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+      CommentReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
+        .await
+        .unwrap();
 
     let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
     expected_jessica_report_view_after_resolve
@@ -558,24 +595,29 @@ mod tests {
     // Do a batch read of timmys reports
     // It should only show saras, which is unresolved
     let reports_after_resolve = CommentReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .my_person_id(inserted_timmy.id)
       .admin(false)
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(reports_after_resolve[0], expected_sara_report_view);
     assert_eq!(reports_after_resolve.len(), 1);
 
     // Make sure the counts are correct
     let report_count_after_resolved =
-      CommentReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
+      CommentReportView::get_report_count(pool, inserted_timmy.id, false, None)
+        .await
+        .unwrap();
     assert_eq!(1, report_count_after_resolved);
 
-    Person::delete(conn, inserted_timmy.id).unwrap();
-    Person::delete(conn, inserted_sara.id).unwrap();
-    Person::delete(conn, inserted_jessica.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Person::delete(pool, inserted_timmy.id).await.unwrap();
+    Person::delete(pool, inserted_sara.id).await.unwrap();
+    Person::delete(pool, inserted_jessica.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs
index 5a94d37a..15ec034f 100644
--- a/crates/db_views/src/comment_view.rs
+++ b/crates/db_views/src/comment_view.rs
@@ -1,5 +1,15 @@
 use crate::structs::CommentView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  PgTextExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use diesel_ltree::{nlevel, subpath, Ltree, LtreeExtensions};
 use lemmy_db_schema::{
   aggregates::structs::CommentAggregates,
@@ -27,7 +37,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::{functions::hot_rank, fuzzy_search, limit_and_offset_unlimited},
+  utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset_unlimited, DbPool},
   CommentSortType,
   ListingType,
 };
@@ -47,11 +57,13 @@ type CommentViewTuple = (
 );
 
 impl CommentView {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     comment_id: CommentId,
     my_person_id: Option<PersonId>,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     // The left join below will return None in this case
     let person_id_join = my_person_id.unwrap_or(PersonId(-1));
 
@@ -124,7 +136,8 @@ impl CommentView {
         person_block::all_columns.nullable(),
         comment_like::score.nullable(),
       ))
-      .first::<CommentViewTuple>(conn)?;
+      .first::<CommentViewTuple>(conn)
+      .await?;
 
     // If a person is given, then my_vote, if None, should be 0, not null
     // Necessary to differentiate between other person's votes
@@ -153,7 +166,7 @@ impl CommentView {
 #[builder(field_defaults(default))]
 pub struct CommentQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   listing_type: Option<ListingType>,
   sort: Option<CommentSortType>,
   community_id: Option<CommunityId>,
@@ -171,8 +184,9 @@ pub struct CommentQuery<'a> {
 }
 
 impl<'a> CommentQuery<'a> {
-  pub fn list(self) -> Result<Vec<CommentView>, Error> {
+  pub async fn list(self) -> Result<Vec<CommentView>, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(self.pool).await?;
 
     // The left join below will return None in this case
     let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
@@ -359,7 +373,8 @@ impl<'a> CommentQuery<'a> {
     let res = query
       .limit(limit)
       .offset(offset)
-      .load::<CommentViewTuple>(self.conn)?;
+      .load::<CommentViewTuple>(conn)
+      .await?;
 
     Ok(CommentView::from_tuple_to_vec(res))
   }
@@ -404,7 +419,7 @@ mod tests {
       post::*,
     },
     traits::{Blockable, Crud, Likeable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
     SubscribedType,
   };
   use serial_test::serial;
@@ -421,27 +436,27 @@ mod tests {
     inserted_community: Community,
   }
 
-  fn init_data(conn: &mut PgConnection) -> Data {
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+  async fn init_data(pool: &DbPool) -> Data {
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("timmy".into())
       .public_key("pubkey".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_person.id)
       .password_encrypted("".to_string())
       .build();
-    let inserted_local_user = LocalUser::create(conn, &local_user_form).unwrap();
+    let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
 
     let new_person_2 = PersonInsertForm::builder()
       .name("sara".into())
       .public_key("pubkey".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let inserted_person_2 = Person::create(conn, &new_person_2).unwrap();
+    let inserted_person_2 = Person::create(pool, &new_person_2).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community 5".to_string())
@@ -450,7 +465,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post 2".into())
@@ -458,7 +473,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     // Create a comment tree with this hierarchy
     //       0
@@ -474,7 +489,7 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment_0 = Comment::create(conn, &comment_form_0, None).unwrap();
+    let inserted_comment_0 = Comment::create(pool, &comment_form_0, None).await.unwrap();
 
     let comment_form_1 = CommentInsertForm::builder()
       .content("Comment 1, A test blocked comment".into())
@@ -482,10 +497,11 @@ mod tests {
       .post_id(inserted_post.id)
       .build();
 
-    let inserted_comment_1 =
-      Comment::create(conn, &comment_form_1, Some(&inserted_comment_0.path)).unwrap();
+    let inserted_comment_1 = Comment::create(pool, &comment_form_1, Some(&inserted_comment_0.path))
+      .await
+      .unwrap();
 
-    let finnish_id = Language::read_id_from_code(conn, "fi").unwrap();
+    let finnish_id = Language::read_id_from_code(pool, "fi").await.unwrap();
     let comment_form_2 = CommentInsertForm::builder()
       .content("Comment 2".into())
       .creator_id(inserted_person.id)
@@ -493,8 +509,9 @@ mod tests {
       .language_id(Some(finnish_id))
       .build();
 
-    let inserted_comment_2 =
-      Comment::create(conn, &comment_form_2, Some(&inserted_comment_0.path)).unwrap();
+    let inserted_comment_2 = Comment::create(pool, &comment_form_2, Some(&inserted_comment_0.path))
+      .await
+      .unwrap();
 
     let comment_form_3 = CommentInsertForm::builder()
       .content("Comment 3".into())
@@ -503,9 +520,11 @@ mod tests {
       .build();
 
     let _inserted_comment_3 =
-      Comment::create(conn, &comment_form_3, Some(&inserted_comment_1.path)).unwrap();
+      Comment::create(pool, &comment_form_3, Some(&inserted_comment_1.path))
+        .await
+        .unwrap();
 
-    let polish_id = Language::read_id_from_code(conn, "pl").unwrap();
+    let polish_id = Language::read_id_from_code(pool, "pl").await.unwrap();
     let comment_form_4 = CommentInsertForm::builder()
       .content("Comment 4".into())
       .creator_id(inserted_person.id)
@@ -513,8 +532,9 @@ mod tests {
       .language_id(Some(polish_id))
       .build();
 
-    let inserted_comment_4 =
-      Comment::create(conn, &comment_form_4, Some(&inserted_comment_1.path)).unwrap();
+    let inserted_comment_4 = Comment::create(pool, &comment_form_4, Some(&inserted_comment_1.path))
+      .await
+      .unwrap();
 
     let comment_form_5 = CommentInsertForm::builder()
       .content("Comment 5".into())
@@ -523,14 +543,18 @@ mod tests {
       .build();
 
     let _inserted_comment_5 =
-      Comment::create(conn, &comment_form_5, Some(&inserted_comment_4.path)).unwrap();
+      Comment::create(pool, &comment_form_5, Some(&inserted_comment_4.path))
+        .await
+        .unwrap();
 
     let timmy_blocks_sara_form = PersonBlockForm {
       person_id: inserted_person.id,
       target_id: inserted_person_2.id,
     };
 
-    let inserted_block = PersonBlock::block(conn, &timmy_blocks_sara_form).unwrap();
+    let inserted_block = PersonBlock::block(pool, &timmy_blocks_sara_form)
+      .await
+      .unwrap();
 
     let expected_block = PersonBlock {
       id: inserted_block.id,
@@ -547,7 +571,7 @@ mod tests {
       score: 1,
     };
 
-    let _inserted_comment_like = CommentLike::like(conn, &comment_like_form).unwrap();
+    let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap();
 
     Data {
       inserted_instance,
@@ -562,22 +586,23 @@ mod tests {
     }
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
-    let expected_comment_view_no_person = expected_comment_view(&data, conn);
+    let expected_comment_view_no_person = expected_comment_view(&data, pool).await;
 
     let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned();
     expected_comment_view_with_person.my_vote = Some(1);
 
     let read_comment_views_no_person = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .build()
       .list()
+      .await
       .unwrap();
 
     assert_eq!(
@@ -586,11 +611,12 @@ mod tests {
     );
 
     let read_comment_views_with_person = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
 
     assert_eq!(
@@ -602,40 +628,43 @@ mod tests {
     assert_eq!(5, read_comment_views_with_person.len());
 
     let read_comment_from_blocked_person = CommentView::read(
-      conn,
+      pool,
       data.inserted_comment_1.id,
       Some(data.inserted_person.id),
     )
+    .await
     .unwrap();
 
     // Make sure block set the creator blocked
     assert!(read_comment_from_blocked_person.creator_blocked);
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_comment_tree() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn test_comment_tree() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     let top_path = data.inserted_comment_0.path.clone();
     let read_comment_views_top_path = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .parent_path(Some(top_path))
       .build()
       .list()
+      .await
       .unwrap();
 
     let child_path = data.inserted_comment_1.path.clone();
     let read_comment_views_child_path = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .parent_path(Some(child_path))
       .build()
       .list()
+      .await
       .unwrap();
 
     // Make sure the comment parent-limited fetch is correct
@@ -651,29 +680,31 @@ mod tests {
     assert!(!child_comments.contains(&data.inserted_comment_2));
 
     let read_comment_views_top_max_depth = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .max_depth(Some(1))
       .build()
       .list()
+      .await
       .unwrap();
 
     // Make sure a depth limited one only has the top comment
     assert_eq!(
-      expected_comment_view(&data, conn),
+      expected_comment_view(&data, pool).await,
       read_comment_views_top_max_depth[0]
     );
     assert_eq!(1, read_comment_views_top_max_depth.len());
 
     let child_path = data.inserted_comment_1.path.clone();
     let read_comment_views_parent_max_depth = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .post_id(Some(data.inserted_post.id))
       .parent_path(Some(child_path))
       .max_depth(Some(1))
       .sort(Some(CommentSortType::New))
       .build()
       .list()
+      .await
       .unwrap();
 
     // Make sure a depth limited one, and given child comment 1, has 3
@@ -683,33 +714,37 @@ mod tests {
       .eq("Comment 3"));
     assert_eq!(3, read_comment_views_parent_max_depth.len());
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_languages() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn test_languages() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     // by default, user has all languages enabled and should see all comments
     // (except from blocked user)
     let all_languages = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(5, all_languages.len());
 
     // change user lang to finnish, should only show single finnish comment
-    let finnish_id = Language::read_id_from_code(conn, "fi").unwrap();
-    LocalUserLanguage::update(conn, vec![finnish_id], data.inserted_local_user.id).unwrap();
+    let finnish_id = Language::read_id_from_code(pool, "fi").await.unwrap();
+    LocalUserLanguage::update(pool, vec![finnish_id], data.inserted_local_user.id)
+      .await
+      .unwrap();
     let finnish_comment = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(1, finnish_comment.len());
     assert_eq!(
@@ -719,32 +754,49 @@ mod tests {
     assert_eq!(finnish_id, finnish_comment[0].comment.language_id);
 
     // now show all comments with undetermined language (which is the default value)
-    let undetermined_id = Language::read_id_from_code(conn, "und").unwrap();
-    LocalUserLanguage::update(conn, vec![undetermined_id], data.inserted_local_user.id).unwrap();
+    let undetermined_id = Language::read_id_from_code(pool, "und").await.unwrap();
+    LocalUserLanguage::update(pool, vec![undetermined_id], data.inserted_local_user.id)
+      .await
+      .unwrap();
     let undetermined_comment = CommentQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(3, undetermined_comment.len());
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  fn cleanup(data: Data, conn: &mut PgConnection) {
-    CommentLike::remove(conn, data.inserted_person.id, data.inserted_comment_0.id).unwrap();
-    Comment::delete(conn, data.inserted_comment_0.id).unwrap();
-    Comment::delete(conn, data.inserted_comment_1.id).unwrap();
-    Post::delete(conn, data.inserted_post.id).unwrap();
-    Community::delete(conn, data.inserted_community.id).unwrap();
-    Person::delete(conn, data.inserted_person.id).unwrap();
-    Person::delete(conn, data.inserted_person_2.id).unwrap();
-    Instance::delete(conn, data.inserted_instance.id).unwrap();
+  async fn cleanup(data: Data, pool: &DbPool) {
+    CommentLike::remove(pool, data.inserted_person.id, data.inserted_comment_0.id)
+      .await
+      .unwrap();
+    Comment::delete(pool, data.inserted_comment_0.id)
+      .await
+      .unwrap();
+    Comment::delete(pool, data.inserted_comment_1.id)
+      .await
+      .unwrap();
+    Post::delete(pool, data.inserted_post.id).await.unwrap();
+    Community::delete(pool, data.inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, data.inserted_person.id).await.unwrap();
+    Person::delete(pool, data.inserted_person_2.id)
+      .await
+      .unwrap();
+    Instance::delete(pool, data.inserted_instance.id)
+      .await
+      .unwrap();
   }
 
-  fn expected_comment_view(data: &Data, conn: &mut PgConnection) -> CommentView {
-    let agg = CommentAggregates::read(conn, data.inserted_comment_0.id).unwrap();
+  async fn expected_comment_view(data: &Data, pool: &DbPool) -> CommentView {
+    let agg = CommentAggregates::read(pool, data.inserted_comment_0.id)
+      .await
+      .unwrap();
     CommentView {
       creator_banned_from_community: false,
       my_vote: None,
diff --git a/crates/db_views/src/local_user_discussion_language_view.rs b/crates/db_views/src/local_user_discussion_language_view.rs
index 0268de1c..9ffa47ec 100644
--- a/crates/db_views/src/local_user_discussion_language_view.rs
+++ b/crates/db_views/src/local_user_discussion_language_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::LocalUserDiscussionLanguageView;
-use diesel::{result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::LocalUserId,
   schema::{language, local_user, local_user_language},
@@ -8,15 +9,18 @@ use lemmy_db_schema::{
     local_user::{LocalUser, LocalUserSettings},
   },
   traits::ToSafeSettings,
+  utils::{get_conn, DbPool},
 };
 
 type LocalUserDiscussionLanguageViewTuple = (LocalUserSettings, Language);
 
 impl LocalUserDiscussionLanguageView {
-  pub fn read_languages(
-    conn: &mut PgConnection,
+  pub async fn read_languages(
+    pool: &DbPool,
     local_user_id: LocalUserId,
   ) -> Result<Vec<Language>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let res = local_user_language::table
       .inner_join(local_user::table)
       .inner_join(language::table)
@@ -25,7 +29,8 @@ impl LocalUserDiscussionLanguageView {
         language::all_columns,
       ))
       .filter(local_user::id.eq(local_user_id))
-      .load::<LocalUserDiscussionLanguageViewTuple>(conn)?;
+      .load::<LocalUserDiscussionLanguageViewTuple>(conn)
+      .await?;
 
     Ok(res.into_iter().map(|a| a.1).collect::<Vec<Language>>())
   }
diff --git a/crates/db_views/src/local_user_view.rs b/crates/db_views/src/local_user_view.rs
index b5a758b8..da735aae 100644
--- a/crates/db_views/src/local_user_view.rs
+++ b/crates/db_views/src/local_user_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::{LocalUserSettingsView, LocalUserView};
-use diesel::{result::Error, *};
+use diesel::{result::Error, BoolExpressionMethods, ExpressionMethods, JoinOnDsl, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::PersonAggregates,
   newtypes::{LocalUserId, PersonId},
@@ -9,13 +10,15 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ToSafeSettings, ViewToVec},
-  utils::functions::lower,
+  utils::{functions::lower, get_conn, DbPool},
 };
 
 type LocalUserViewTuple = (LocalUser, Person, PersonAggregates);
 
 impl LocalUserView {
-  pub fn read(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let (local_user, person, counts) = local_user::table
       .find(local_user_id)
       .inner_join(person::table)
@@ -25,7 +28,8 @@ impl LocalUserView {
         person::all_columns,
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserViewTuple>(conn)?;
+      .first::<LocalUserViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -33,7 +37,8 @@ impl LocalUserView {
     })
   }
 
-  pub fn read_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
+  pub async fn read_person(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (local_user, person, counts) = local_user::table
       .filter(person::id.eq(person_id))
       .inner_join(person::table)
@@ -43,7 +48,8 @@ impl LocalUserView {
         person::all_columns,
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserViewTuple>(conn)?;
+      .first::<LocalUserViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -52,7 +58,8 @@ impl LocalUserView {
   }
 
   // TODO check where this is used
-  pub fn read_from_name(conn: &mut PgConnection, name: &str) -> Result<Self, Error> {
+  pub async fn read_from_name(pool: &DbPool, name: &str) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (local_user, person, counts) = local_user::table
       .filter(person::name.eq(name))
       .inner_join(person::table)
@@ -62,7 +69,8 @@ impl LocalUserView {
         person::all_columns,
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserViewTuple>(conn)?;
+      .first::<LocalUserViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -70,10 +78,8 @@ impl LocalUserView {
     })
   }
 
-  pub fn find_by_email_or_name(
-    conn: &mut PgConnection,
-    name_or_email: &str,
-  ) -> Result<Self, Error> {
+  pub async fn find_by_email_or_name(pool: &DbPool, name_or_email: &str) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (local_user, person, counts) = local_user::table
       .inner_join(person::table)
       .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
@@ -87,7 +93,8 @@ impl LocalUserView {
         person::all_columns,
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserViewTuple>(conn)?;
+      .first::<LocalUserViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -95,7 +102,8 @@ impl LocalUserView {
     })
   }
 
-  pub fn find_by_email(conn: &mut PgConnection, from_email: &str) -> Result<Self, Error> {
+  pub async fn find_by_email(pool: &DbPool, from_email: &str) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (local_user, person, counts) = local_user::table
       .inner_join(person::table)
       .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id)))
@@ -105,7 +113,8 @@ impl LocalUserView {
         person::all_columns,
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserViewTuple>(conn)?;
+      .first::<LocalUserViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -117,7 +126,8 @@ impl LocalUserView {
 type LocalUserSettingsViewTuple = (LocalUserSettings, PersonSafe, PersonAggregates);
 
 impl LocalUserSettingsView {
-  pub fn read(conn: &mut PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, local_user_id: LocalUserId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (local_user, person, counts) = local_user::table
       .find(local_user_id)
       .inner_join(person::table)
@@ -127,7 +137,8 @@ impl LocalUserSettingsView {
         Person::safe_columns_tuple(),
         person_aggregates::all_columns,
       ))
-      .first::<LocalUserSettingsViewTuple>(conn)?;
+      .first::<LocalUserSettingsViewTuple>(conn)
+      .await?;
     Ok(Self {
       local_user,
       person,
@@ -135,7 +146,8 @@ impl LocalUserSettingsView {
     })
   }
 
-  pub fn list_admins_with_emails(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
+  pub async fn list_admins_with_emails(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = local_user::table
       .filter(person::admin.eq(true))
       .filter(local_user::email.is_not_null())
@@ -146,7 +158,8 @@ impl LocalUserSettingsView {
         Person::safe_columns_tuple(),
         person_aggregates::all_columns,
       ))
-      .load::<LocalUserSettingsViewTuple>(conn)?;
+      .load::<LocalUserSettingsViewTuple>(conn)
+      .await?;
 
     Ok(LocalUserSettingsView::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs
index 83c43ff4..555a65ae 100644
--- a/crates/db_views/src/post_report_view.rs
+++ b/crates/db_views/src/post_report_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::PostReportView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::PostAggregates,
   newtypes::{CommunityId, PersonId, PostReportId},
@@ -20,7 +29,7 @@ use lemmy_db_schema::{
     post_report::PostReport,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 use typed_builder::TypedBuilder;
 
@@ -40,11 +49,12 @@ impl PostReportView {
   /// returns the PostReportView for the provided report_id
   ///
   /// * `report_id` - the report id to obtain
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     report_id: PostReportId,
     my_person_id: PersonId,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let (
@@ -97,7 +107,8 @@ impl PostReportView {
         post_aggregates::all_columns,
         person_alias_2.fields(Person::safe_columns_tuple().nullable()),
       ))
-      .first::<PostReportViewTuple>(conn)?;
+      .first::<PostReportViewTuple>(conn)
+      .await?;
 
     let my_vote = post_like;
 
@@ -115,13 +126,14 @@ impl PostReportView {
   }
 
   /// returns the current unresolved post report count for the communities you mod
-  pub fn get_report_count(
-    conn: &mut PgConnection,
+  pub async fn get_report_count(
+    pool: &DbPool,
     my_person_id: PersonId,
     admin: bool,
     community_id: Option<CommunityId>,
   ) -> Result<i64, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     let mut query = post_report::table
       .inner_join(post::table)
       .filter(post_report::resolved.eq(false))
@@ -143,8 +155,12 @@ impl PostReportView {
         )
         .select(count(post_report::id))
         .first::<i64>(conn)
+        .await
     } else {
-      query.select(count(post_report::id)).first::<i64>(conn)
+      query
+        .select(count(post_report::id))
+        .first::<i64>(conn)
+        .await
     }
   }
 }
@@ -153,7 +169,7 @@ impl PostReportView {
 #[builder(field_defaults(default))]
 pub struct PostReportQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   #[builder(!default)]
   my_person_id: PersonId,
   #[builder(!default)]
@@ -165,7 +181,8 @@ pub struct PostReportQuery<'a> {
 }
 
 impl<'a> PostReportQuery<'a> {
-  pub fn list(self) -> Result<Vec<PostReportView>, Error> {
+  pub async fn list(self) -> Result<Vec<PostReportView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let mut query = post_report::table
@@ -236,9 +253,10 @@ impl<'a> PostReportQuery<'a> {
               .and(community_moderator::person_id.eq(self.my_person_id)),
           ),
         )
-        .load::<PostReportViewTuple>(self.conn)?
+        .load::<PostReportViewTuple>(conn)
+        .await?
     } else {
-      query.load::<PostReportViewTuple>(self.conn)?
+      query.load::<PostReportViewTuple>(conn).await?
     };
 
     Ok(PostReportView::from_tuple_to_vec(res))
@@ -278,16 +296,16 @@ mod tests {
       post_report::{PostReport, PostReportForm},
     },
     traits::{Crud, Joinable, Reportable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person = PersonInsertForm::builder()
       .name("timmy_prv".into())
@@ -295,7 +313,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_timmy = Person::create(conn, &new_person).unwrap();
+    let inserted_timmy = Person::create(pool, &new_person).await.unwrap();
 
     let new_person_2 = PersonInsertForm::builder()
       .name("sara_prv".into())
@@ -303,7 +321,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_sara = Person::create(conn, &new_person_2).unwrap();
+    let inserted_sara = Person::create(pool, &new_person_2).await.unwrap();
 
     // Add a third person, since new ppl can only report something once.
     let new_person_3 = PersonInsertForm::builder()
@@ -312,7 +330,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_jessica = Person::create(conn, &new_person_3).unwrap();
+    let inserted_jessica = Person::create(pool, &new_person_3).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test community prv".to_string())
@@ -321,7 +339,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     // Make timmy a mod
     let timmy_moderator_form = CommunityModeratorForm {
@@ -329,7 +347,9 @@ mod tests {
       person_id: inserted_timmy.id,
     };
 
-    let _inserted_moderator = CommunityModerator::join(conn, &timmy_moderator_form).unwrap();
+    let _inserted_moderator = CommunityModerator::join(pool, &timmy_moderator_form)
+      .await
+      .unwrap();
 
     let new_post = PostInsertForm::builder()
       .name("A test post crv".into())
@@ -337,7 +357,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     // sara reports
     let sara_report_form = PostReportForm {
@@ -349,7 +369,7 @@ mod tests {
       reason: "from sara".into(),
     };
 
-    let inserted_sara_report = PostReport::report(conn, &sara_report_form).unwrap();
+    let inserted_sara_report = PostReport::report(pool, &sara_report_form).await.unwrap();
 
     // jessica reports
     let jessica_report_form = PostReportForm {
@@ -361,12 +381,16 @@ mod tests {
       reason: "from jessica".into(),
     };
 
-    let inserted_jessica_report = PostReport::report(conn, &jessica_report_form).unwrap();
+    let inserted_jessica_report = PostReport::report(pool, &jessica_report_form)
+      .await
+      .unwrap();
 
-    let agg = PostAggregates::read(conn, inserted_post.id).unwrap();
+    let agg = PostAggregates::read(pool, inserted_post.id).await.unwrap();
 
     let read_jessica_report_view =
-      PostReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+      PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
+        .await
+        .unwrap();
     let expected_jessica_report_view = PostReportView {
       post_report: inserted_jessica_report.to_owned(),
       post: inserted_post.to_owned(),
@@ -476,11 +500,12 @@ mod tests {
 
     // Do a batch read of timmys reports
     let reports = PostReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .my_person_id(inserted_timmy.id)
       .admin(false)
       .build()
       .list()
+      .await
       .unwrap();
 
     assert_eq!(
@@ -492,14 +517,19 @@ mod tests {
     );
 
     // Make sure the counts are correct
-    let report_count =
-      PostReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
+    let report_count = PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
+      .await
+      .unwrap();
     assert_eq!(2, report_count);
 
     // Try to resolve the report
-    PostReport::resolve(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+    PostReport::resolve(pool, inserted_jessica_report.id, inserted_timmy.id)
+      .await
+      .unwrap();
     let read_jessica_report_view_after_resolve =
-      PostReportView::read(conn, inserted_jessica_report.id, inserted_timmy.id).unwrap();
+      PostReportView::read(pool, inserted_jessica_report.id, inserted_timmy.id)
+        .await
+        .unwrap();
 
     let mut expected_jessica_report_view_after_resolve = expected_jessica_report_view;
     expected_jessica_report_view_after_resolve
@@ -541,23 +571,28 @@ mod tests {
     // Do a batch read of timmys reports
     // It should only show saras, which is unresolved
     let reports_after_resolve = PostReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .my_person_id(inserted_timmy.id)
       .admin(false)
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(reports_after_resolve[0], expected_sara_report_view);
 
     // Make sure the counts are correct
     let report_count_after_resolved =
-      PostReportView::get_report_count(conn, inserted_timmy.id, false, None).unwrap();
+      PostReportView::get_report_count(pool, inserted_timmy.id, false, None)
+        .await
+        .unwrap();
     assert_eq!(1, report_count_after_resolved);
 
-    Person::delete(conn, inserted_timmy.id).unwrap();
-    Person::delete(conn, inserted_sara.id).unwrap();
-    Person::delete(conn, inserted_jessica.id).unwrap();
-    Community::delete(conn, inserted_community.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Person::delete(pool, inserted_timmy.id).await.unwrap();
+    Person::delete(pool, inserted_sara.id).await.unwrap();
+    Person::delete(pool, inserted_jessica.id).await.unwrap();
+    Community::delete(pool, inserted_community.id)
+      .await
+      .unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs
index aebddc1c..d47db578 100644
--- a/crates/db_views/src/post_view.rs
+++ b/crates/db_views/src/post_view.rs
@@ -1,5 +1,19 @@
 use crate::structs::PostView;
-use diesel::{dsl::*, pg::Pg, result::Error, *};
+use diesel::{
+  debug_query,
+  dsl::*,
+  pg::Pg,
+  result::Error,
+  sql_function,
+  sql_types,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  PgTextExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::PostAggregates,
   newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
@@ -26,7 +40,7 @@ use lemmy_db_schema::{
     post::{Post, PostRead, PostSaved},
   },
   traits::{ToSafe, ViewToVec},
-  utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
+  utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset, DbPool},
   ListingType,
   SortType,
 };
@@ -50,11 +64,13 @@ type PostViewTuple = (
 sql_function!(fn coalesce(x: sql_types::Nullable<sql_types::BigInt>, y: sql_types::BigInt) -> sql_types::BigInt);
 
 impl PostView {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     post_id: PostId,
     my_person_id: Option<PersonId>,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     // The left join below will return None in this case
     let person_id_join = my_person_id.unwrap_or(PersonId(-1));
     let (
@@ -144,7 +160,8 @@ impl PostView {
           post_aggregates::comments,
         ),
       ))
-      .first::<PostViewTuple>(conn)?;
+      .first::<PostViewTuple>(conn)
+      .await?;
 
     // If a person is given, then my_vote, if None, should be 0, not null
     // Necessary to differentiate between other person's votes
@@ -174,7 +191,7 @@ impl PostView {
 #[builder(field_defaults(default))]
 pub struct PostQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   listing_type: Option<ListingType>,
   sort: Option<SortType>,
   creator_id: Option<PersonId>,
@@ -189,8 +206,9 @@ pub struct PostQuery<'a> {
 }
 
 impl<'a> PostQuery<'a> {
-  pub fn list(self) -> Result<Vec<PostView>, Error> {
+  pub async fn list(self) -> Result<Vec<PostView>, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(self.pool).await?;
 
     // The left join below will return None in this case
     let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
@@ -418,7 +436,7 @@ impl<'a> PostQuery<'a> {
 
     debug!("Post View Query: {:?}", debug_query::<Pg, _>(&query));
 
-    let res = query.load::<PostViewTuple>(self.conn)?;
+    let res = query.load::<PostViewTuple>(conn).await?;
 
     Ok(PostView::from_tuple_to_vec(res))
   }
@@ -449,7 +467,6 @@ impl ViewToVec for PostView {
 #[cfg(test)]
 mod tests {
   use crate::post_view::{PostQuery, PostView};
-  use diesel::PgConnection;
   use lemmy_db_schema::{
     aggregates::structs::PostAggregates,
     newtypes::LanguageId,
@@ -465,7 +482,7 @@ mod tests {
       post::*,
     },
     traits::{Blockable, Crud, Likeable},
-    utils::establish_unpooled_connection,
+    utils::{build_db_pool_for_tests, DbPool},
     SortType,
     SubscribedType,
   };
@@ -481,8 +498,8 @@ mod tests {
     inserted_post: Post,
   }
 
-  fn init_data(conn: &mut PgConnection) -> Data {
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+  async fn init_data(pool: &DbPool) -> Data {
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let person_name = "tegan".to_string();
 
@@ -492,13 +509,13 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_person = Person::create(conn, &new_person).unwrap();
+    let inserted_person = Person::create(pool, &new_person).await.unwrap();
 
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_person.id)
       .password_encrypted("".to_string())
       .build();
-    let inserted_local_user = LocalUser::create(conn, &local_user_form).unwrap();
+    let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
 
     let new_bot = PersonInsertForm::builder()
       .name("mybot".to_string())
@@ -507,7 +524,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_bot = Person::create(conn, &new_bot).unwrap();
+    let inserted_bot = Person::create(pool, &new_bot).await.unwrap();
 
     let new_community = CommunityInsertForm::builder()
       .name("test_community_3".to_string())
@@ -516,7 +533,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_community = Community::create(conn, &new_community).unwrap();
+    let inserted_community = Community::create(pool, &new_community).await.unwrap();
 
     // Test a person block, make sure the post query doesn't include their post
     let blocked_person = PersonInsertForm::builder()
@@ -525,7 +542,7 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_blocked_person = Person::create(conn, &blocked_person).unwrap();
+    let inserted_blocked_person = Person::create(pool, &blocked_person).await.unwrap();
 
     let post_from_blocked_person = PostInsertForm::builder()
       .name("blocked_person_post".to_string())
@@ -534,7 +551,7 @@ mod tests {
       .language_id(Some(LanguageId(1)))
       .build();
 
-    Post::create(conn, &post_from_blocked_person).unwrap();
+    Post::create(pool, &post_from_blocked_person).await.unwrap();
 
     // block that person
     let person_block = PersonBlockForm {
@@ -542,7 +559,7 @@ mod tests {
       target_id: inserted_blocked_person.id,
     };
 
-    PersonBlock::block(conn, &person_block).unwrap();
+    PersonBlock::block(pool, &person_block).await.unwrap();
 
     // A sample post
     let new_post = PostInsertForm::builder()
@@ -552,7 +569,7 @@ mod tests {
       .language_id(Some(LanguageId(47)))
       .build();
 
-    let inserted_post = Post::create(conn, &new_post).unwrap();
+    let inserted_post = Post::create(pool, &new_post).await.unwrap();
 
     let new_bot_post = PostInsertForm::builder()
       .name("test bot post".to_string())
@@ -560,7 +577,7 @@ mod tests {
       .community_id(inserted_community.id)
       .build();
 
-    let _inserted_bot_post = Post::create(conn, &new_bot_post).unwrap();
+    let _inserted_bot_post = Post::create(pool, &new_bot_post).await.unwrap();
 
     Data {
       inserted_instance,
@@ -573,31 +590,36 @@ mod tests {
     }
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn post_listing_with_person() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn post_listing_with_person() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     let local_user_form = LocalUserUpdateForm::builder()
       .show_bot_accounts(Some(false))
       .build();
     let inserted_local_user =
-      LocalUser::update(conn, data.inserted_local_user.id, &local_user_form).unwrap();
+      LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
+        .await
+        .unwrap();
 
     let read_post_listing = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .community_id(Some(data.inserted_community.id))
       .local_user(Some(&inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
 
     let post_listing_single_with_person =
-      PostView::read(conn, data.inserted_post.id, Some(data.inserted_person.id)).unwrap();
+      PostView::read(pool, data.inserted_post.id, Some(data.inserted_person.id))
+        .await
+        .unwrap();
 
-    let mut expected_post_listing_with_user = expected_post_view(&data, conn);
+    let mut expected_post_listing_with_user = expected_post_view(&data, pool).await;
 
     // Should be only one person, IE the bot post, and blocked should be missing
     assert_eq!(1, read_post_listing.len());
@@ -613,40 +635,45 @@ mod tests {
       .show_bot_accounts(Some(true))
       .build();
     let inserted_local_user =
-      LocalUser::update(conn, data.inserted_local_user.id, &local_user_form).unwrap();
+      LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
+        .await
+        .unwrap();
 
     let post_listings_with_bots = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .community_id(Some(data.inserted_community.id))
       .local_user(Some(&inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
     // should include bot post which has "undetermined" language
     assert_eq!(2, post_listings_with_bots.len());
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn post_listing_no_person() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn post_listing_no_person() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     let read_post_listing_multiple_no_person = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .community_id(Some(data.inserted_community.id))
       .build()
       .list()
+      .await
       .unwrap();
 
-    let read_post_listing_single_no_person =
-      PostView::read(conn, data.inserted_post.id, None).unwrap();
+    let read_post_listing_single_no_person = PostView::read(pool, data.inserted_post.id, None)
+      .await
+      .unwrap();
 
-    let expected_post_listing_no_person = expected_post_view(&data, conn);
+    let expected_post_listing_no_person = expected_post_view(&data, pool).await;
 
     // Should be 2 posts, with the bot post, and the blocked
     assert_eq!(3, read_post_listing_multiple_no_person.len());
@@ -660,41 +687,44 @@ mod tests {
       read_post_listing_single_no_person
     );
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn post_listing_block_community() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn post_listing_block_community() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     let community_block = CommunityBlockForm {
       person_id: data.inserted_person.id,
       community_id: data.inserted_community.id,
     };
-    CommunityBlock::block(conn, &community_block).unwrap();
+    CommunityBlock::block(pool, &community_block).await.unwrap();
 
     let read_post_listings_with_person_after_block = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .community_id(Some(data.inserted_community.id))
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
     // Should be 0 posts after the community block
     assert_eq!(0, read_post_listings_with_person_after_block.len());
 
-    CommunityBlock::unblock(conn, &community_block).unwrap();
-    cleanup(data, conn);
+    CommunityBlock::unblock(pool, &community_block)
+      .await
+      .unwrap();
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn post_listing_like() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn post_listing_like() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
     let post_like_form = PostLikeForm {
       post_id: data.inserted_post.id,
@@ -702,7 +732,7 @@ mod tests {
       score: 1,
     };
 
-    let inserted_post_like = PostLike::like(conn, &post_like_form).unwrap();
+    let inserted_post_like = PostLike::like(pool, &post_like_form).await.unwrap();
 
     let expected_post_like = PostLike {
       id: inserted_post_like.id,
@@ -713,19 +743,20 @@ mod tests {
     };
     assert_eq!(expected_post_like, inserted_post_like);
 
-    let like_removed =
-      PostLike::remove(conn, data.inserted_person.id, data.inserted_post.id).unwrap();
+    let like_removed = PostLike::remove(pool, data.inserted_person.id, data.inserted_post.id)
+      .await
+      .unwrap();
     assert_eq!(1, like_removed);
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn post_listing_person_language() {
-    let conn = &mut establish_unpooled_connection();
-    let data = init_data(conn);
+  async fn post_listing_person_language() {
+    let pool = &build_db_pool_for_tests().await;
+    let data = init_data(pool).await;
 
-    let spanish_id = Language::read_id_from_code(conn, "es").unwrap();
+    let spanish_id = Language::read_id_from_code(pool, "es").await.unwrap();
     let post_spanish = PostInsertForm::builder()
       .name("asffgdsc".to_string())
       .creator_id(data.inserted_person.id)
@@ -733,47 +764,53 @@ mod tests {
       .language_id(Some(spanish_id))
       .build();
 
-    Post::create(conn, &post_spanish).unwrap();
+    Post::create(pool, &post_spanish).await.unwrap();
 
     let post_listings_all = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
 
     // no language filters specified, all posts should be returned
     assert_eq!(3, post_listings_all.len());
 
-    let french_id = Language::read_id_from_code(conn, "fr").unwrap();
-    LocalUserLanguage::update(conn, vec![french_id], data.inserted_local_user.id).unwrap();
+    let french_id = Language::read_id_from_code(pool, "fr").await.unwrap();
+    LocalUserLanguage::update(pool, vec![french_id], data.inserted_local_user.id)
+      .await
+      .unwrap();
 
     let post_listing_french = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
 
     // only one french language post should be returned
     assert_eq!(1, post_listing_french.len());
     assert_eq!(french_id, post_listing_french[0].post.language_id);
 
-    let undetermined_id = Language::read_id_from_code(conn, "und").unwrap();
+    let undetermined_id = Language::read_id_from_code(pool, "und").await.unwrap();
     LocalUserLanguage::update(
-      conn,
+      pool,
       vec![french_id, undetermined_id],
       data.inserted_local_user.id,
     )
+    .await
     .unwrap();
     let post_listings_french_und = PostQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .sort(Some(SortType::New))
       .local_user(Some(&data.inserted_local_user))
       .build()
       .list()
+      .await
       .unwrap();
 
     // french post and undetermined language post should be returned
@@ -784,26 +821,32 @@ mod tests {
     );
     assert_eq!(french_id, post_listings_french_und[1].post.language_id);
 
-    cleanup(data, conn);
+    cleanup(data, pool).await;
   }
 
-  fn cleanup(data: Data, conn: &mut PgConnection) {
-    let num_deleted = Post::delete(conn, data.inserted_post.id).unwrap();
-    Community::delete(conn, data.inserted_community.id).unwrap();
-    Person::delete(conn, data.inserted_person.id).unwrap();
-    Person::delete(conn, data.inserted_bot.id).unwrap();
-    Person::delete(conn, data.inserted_blocked_person.id).unwrap();
-    Instance::delete(conn, data.inserted_instance.id).unwrap();
+  async fn cleanup(data: Data, pool: &DbPool) {
+    let num_deleted = Post::delete(pool, data.inserted_post.id).await.unwrap();
+    Community::delete(pool, data.inserted_community.id)
+      .await
+      .unwrap();
+    Person::delete(pool, data.inserted_person.id).await.unwrap();
+    Person::delete(pool, data.inserted_bot.id).await.unwrap();
+    Person::delete(pool, data.inserted_blocked_person.id)
+      .await
+      .unwrap();
+    Instance::delete(pool, data.inserted_instance.id)
+      .await
+      .unwrap();
     assert_eq!(1, num_deleted);
   }
 
-  fn expected_post_view(data: &Data, conn: &mut PgConnection) -> PostView {
+  async fn expected_post_view(data: &Data, pool: &DbPool) -> PostView {
     let (inserted_person, inserted_community, inserted_post) = (
       &data.inserted_person,
       &data.inserted_community,
       &data.inserted_post,
     );
-    let agg = PostAggregates::read(conn, inserted_post.id).unwrap();
+    let agg = PostAggregates::read(pool, inserted_post.id).await.unwrap();
 
     PostView {
       post: Post {
diff --git a/crates/db_views/src/private_message_report_view.rs b/crates/db_views/src/private_message_report_view.rs
index 2b198196..75a89ca4 100644
--- a/crates/db_views/src/private_message_report_view.rs
+++ b/crates/db_views/src/private_message_report_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::PrivateMessageReportView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PrivateMessageReportId,
   schema::{person, private_message, private_message_report},
@@ -9,7 +10,7 @@ use lemmy_db_schema::{
     private_message_report::PrivateMessageReport,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 use typed_builder::TypedBuilder;
 
@@ -25,7 +26,8 @@ impl PrivateMessageReportView {
   /// returns the PrivateMessageReportView for the provided report_id
   ///
   /// * `report_id` - the report id to obtain
-  pub fn read(conn: &mut PgConnection, report_id: PrivateMessageReportId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, report_id: PrivateMessageReportId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let (private_message_report, private_message, private_message_creator, creator, resolver) =
@@ -51,7 +53,8 @@ impl PrivateMessageReportView {
             .fields(Person::safe_columns_tuple())
             .nullable(),
         ))
-        .first::<PrivateMessageReportViewTuple>(conn)?;
+        .first::<PrivateMessageReportViewTuple>(conn)
+        .await?;
 
     Ok(Self {
       private_message_report,
@@ -63,8 +66,9 @@ impl PrivateMessageReportView {
   }
 
   /// Returns the current unresolved post report count for the communities you mod
-  pub fn get_report_count(conn: &mut PgConnection) -> Result<i64, Error> {
+  pub async fn get_report_count(pool: &DbPool) -> Result<i64, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(pool).await?;
 
     private_message_report::table
       .inner_join(private_message::table)
@@ -72,6 +76,7 @@ impl PrivateMessageReportView {
       .into_boxed()
       .select(count(private_message_report::id))
       .first::<i64>(conn)
+      .await
   }
 }
 
@@ -79,14 +84,15 @@ impl PrivateMessageReportView {
 #[builder(field_defaults(default))]
 pub struct PrivateMessageReportQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   page: Option<i64>,
   limit: Option<i64>,
   unresolved_only: Option<bool>,
 }
 
 impl<'a> PrivateMessageReportQuery<'a> {
-  pub fn list(self) -> Result<Vec<PrivateMessageReportView>, Error> {
+  pub async fn list(self) -> Result<Vec<PrivateMessageReportView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
     let (person_alias_1, person_alias_2) = diesel::alias!(person as person1, person as person2);
 
     let mut query = private_message_report::table
@@ -121,7 +127,7 @@ impl<'a> PrivateMessageReportQuery<'a> {
       .limit(limit)
       .offset(offset);
 
-    let res = query.load::<PrivateMessageReportViewTuple>(self.conn)?;
+    let res = query.load::<PrivateMessageReportViewTuple>(conn).await?;
 
     Ok(PrivateMessageReportView::from_tuple_to_vec(res))
   }
@@ -154,30 +160,30 @@ mod tests {
       private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
     },
     traits::{Crud, Reportable},
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let new_person_1 = PersonInsertForm::builder()
       .name("timmy_mrv".into())
       .public_key("pubkey".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let inserted_timmy = Person::create(conn, &new_person_1).unwrap();
+    let inserted_timmy = Person::create(pool, &new_person_1).await.unwrap();
 
     let new_person_2 = PersonInsertForm::builder()
       .name("jessica_mrv".into())
       .public_key("pubkey".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let inserted_jessica = Person::create(conn, &new_person_2).unwrap();
+    let inserted_jessica = Person::create(pool, &new_person_2).await.unwrap();
 
     // timmy sends private message to jessica
     let pm_form = PrivateMessageInsertForm::builder()
@@ -185,7 +191,7 @@ mod tests {
       .recipient_id(inserted_jessica.id)
       .content("something offensive".to_string())
       .build();
-    let pm = PrivateMessage::create(conn, &pm_form).unwrap();
+    let pm = PrivateMessage::create(pool, &pm_form).await.unwrap();
 
     // jessica reports private message
     let pm_report_form = PrivateMessageReportForm {
@@ -194,12 +200,15 @@ mod tests {
       private_message_id: pm.id,
       reason: "its offensive".to_string(),
     };
-    let pm_report = PrivateMessageReport::report(conn, &pm_report_form).unwrap();
+    let pm_report = PrivateMessageReport::report(pool, &pm_report_form)
+      .await
+      .unwrap();
 
     let reports = PrivateMessageReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(1, reports.len());
     assert!(!reports[0].private_message_report.resolved);
@@ -213,16 +222,19 @@ mod tests {
       .public_key("pubkey".to_string())
       .instance_id(inserted_instance.id)
       .build();
-    let inserted_admin = Person::create(conn, &new_person_3).unwrap();
+    let inserted_admin = Person::create(pool, &new_person_3).await.unwrap();
 
     // admin resolves the report (after taking appropriate action)
-    PrivateMessageReport::resolve(conn, pm_report.id, inserted_admin.id).unwrap();
+    PrivateMessageReport::resolve(pool, pm_report.id, inserted_admin.id)
+      .await
+      .unwrap();
 
     let reports = PrivateMessageReportQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .unresolved_only(Some(false))
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(1, reports.len());
     assert!(reports[0].private_message_report.resolved);
@@ -232,6 +244,6 @@ mod tests {
       reports[0].resolver.as_ref().unwrap().name
     );
 
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs
index 281df8ba..cfbc2dc9 100644
--- a/crates/db_views/src/private_message_view.rs
+++ b/crates/db_views/src/private_message_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::PrivateMessageView;
-use diesel::{pg::Pg, result::Error, *};
+use diesel::{
+  debug_query,
+  pg::Pg,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::{PersonId, PrivateMessageId},
   schema::{person, private_message},
@@ -8,7 +17,7 @@ use lemmy_db_schema::{
     private_message::PrivateMessage,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 use tracing::debug;
 use typed_builder::TypedBuilder;
@@ -16,10 +25,8 @@ use typed_builder::TypedBuilder;
 type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafe);
 
 impl PrivateMessageView {
-  pub fn read(
-    conn: &mut PgConnection,
-    private_message_id: PrivateMessageId,
-  ) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, private_message_id: PrivateMessageId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let (private_message, creator, recipient) = private_message::table
@@ -34,7 +41,8 @@ impl PrivateMessageView {
         Person::safe_columns_tuple(),
         person_alias_1.fields(Person::safe_columns_tuple()),
       ))
-      .first::<PrivateMessageViewTuple>(conn)?;
+      .first::<PrivateMessageViewTuple>(conn)
+      .await?;
 
     Ok(PrivateMessageView {
       private_message,
@@ -44,17 +52,16 @@ impl PrivateMessageView {
   }
 
   /// Gets the number of unread messages
-  pub fn get_unread_messages(
-    conn: &mut PgConnection,
-    my_person_id: PersonId,
-  ) -> Result<i64, Error> {
+  pub async fn get_unread_messages(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(pool).await?;
     private_message::table
       .filter(private_message::read.eq(false))
       .filter(private_message::recipient_id.eq(my_person_id))
       .filter(private_message::deleted.eq(false))
       .select(count(private_message::id))
       .first::<i64>(conn)
+      .await
   }
 }
 
@@ -62,7 +69,7 @@ impl PrivateMessageView {
 #[builder(field_defaults(default))]
 pub struct PrivateMessageQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   #[builder(!default)]
   recipient_id: PersonId,
   unread_only: Option<bool>,
@@ -71,7 +78,8 @@ pub struct PrivateMessageQuery<'a> {
 }
 
 impl<'a> PrivateMessageQuery<'a> {
-  pub fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
+  pub async fn list(self) -> Result<Vec<PrivateMessageView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let mut query = private_message::table
@@ -114,7 +122,7 @@ impl<'a> PrivateMessageQuery<'a> {
       debug_query::<Pg, _>(&query)
     );
 
-    let res = query.load::<PrivateMessageViewTuple>(self.conn)?;
+    let res = query.load::<PrivateMessageViewTuple>(conn).await?;
 
     Ok(PrivateMessageView::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs
index 265292ef..31f4ad13 100644
--- a/crates/db_views/src/registration_application_view.rs
+++ b/crates/db_views/src/registration_application_view.rs
@@ -1,5 +1,13 @@
 use crate::structs::RegistrationApplicationView;
-use diesel::{dsl::count, result::Error, *};
+use diesel::{
+  dsl::count,
+  result::Error,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   schema::{local_user, person, registration_application},
   source::{
@@ -8,7 +16,7 @@ use lemmy_db_schema::{
     registration_application::RegistrationApplication,
   },
   traits::{ToSafe, ToSafeSettings, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 use typed_builder::TypedBuilder;
 
@@ -20,7 +28,8 @@ type RegistrationApplicationViewTuple = (
 );
 
 impl RegistrationApplicationView {
-  pub fn read(conn: &mut PgConnection, registration_application_id: i32) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, registration_application_id: i32) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let (registration_application, creator_local_user, creator, admin) =
@@ -43,7 +52,8 @@ impl RegistrationApplicationView {
             .fields(Person::safe_columns_tuple())
             .nullable(),
         ))
-        .first::<RegistrationApplicationViewTuple>(conn)?;
+        .first::<RegistrationApplicationViewTuple>(conn)
+        .await?;
 
     Ok(RegistrationApplicationView {
       registration_application,
@@ -54,10 +64,8 @@ impl RegistrationApplicationView {
   }
 
   /// Returns the current unread registration_application count
-  pub fn get_unread_count(
-    conn: &mut PgConnection,
-    verified_email_only: bool,
-  ) -> Result<i64, Error> {
+  pub async fn get_unread_count(pool: &DbPool, verified_email_only: bool) -> Result<i64, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let mut query = registration_application::table
@@ -77,6 +85,7 @@ impl RegistrationApplicationView {
     query
       .select(count(registration_application::id))
       .first::<i64>(conn)
+      .await
   }
 }
 
@@ -84,7 +93,7 @@ impl RegistrationApplicationView {
 #[builder(field_defaults(default))]
 pub struct RegistrationApplicationQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   unread_only: Option<bool>,
   verified_email_only: Option<bool>,
   page: Option<i64>,
@@ -92,7 +101,8 @@ pub struct RegistrationApplicationQuery<'a> {
 }
 
 impl<'a> RegistrationApplicationQuery<'a> {
-  pub fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
+  pub async fn list(self) -> Result<Vec<RegistrationApplicationView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let mut query = registration_application::table
@@ -128,7 +138,7 @@ impl<'a> RegistrationApplicationQuery<'a> {
       .offset(offset)
       .order_by(registration_application::published.desc());
 
-    let res = query.load::<RegistrationApplicationViewTuple>(self.conn)?;
+    let res = query.load::<RegistrationApplicationViewTuple>(conn).await?;
 
     Ok(RegistrationApplicationView::from_tuple_to_vec(res))
   }
@@ -167,16 +177,16 @@ mod tests {
       },
     },
     traits::Crud,
-    utils::establish_unpooled_connection,
+    utils::build_db_pool_for_tests,
   };
   use serial_test::serial;
 
-  #[test]
+  #[tokio::test]
   #[serial]
-  fn test_crud() {
-    let conn = &mut establish_unpooled_connection();
+  async fn test_crud() {
+    let pool = &build_db_pool_for_tests().await;
 
-    let inserted_instance = Instance::create(conn, "my_domain.tld").unwrap();
+    let inserted_instance = Instance::create(pool, "my_domain.tld").await.unwrap();
 
     let timmy_person_form = PersonInsertForm::builder()
       .name("timmy_rav".into())
@@ -185,14 +195,16 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_timmy_person = Person::create(conn, &timmy_person_form).unwrap();
+    let inserted_timmy_person = Person::create(pool, &timmy_person_form).await.unwrap();
 
     let timmy_local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_timmy_person.id)
       .password_encrypted("nada".to_string())
       .build();
 
-    let _inserted_timmy_local_user = LocalUser::create(conn, &timmy_local_user_form).unwrap();
+    let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
+      .await
+      .unwrap();
 
     let sara_person_form = PersonInsertForm::builder()
       .name("sara_rav".into())
@@ -200,14 +212,16 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_sara_person = Person::create(conn, &sara_person_form).unwrap();
+    let inserted_sara_person = Person::create(pool, &sara_person_form).await.unwrap();
 
     let sara_local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_sara_person.id)
       .password_encrypted("nada".to_string())
       .build();
 
-    let inserted_sara_local_user = LocalUser::create(conn, &sara_local_user_form).unwrap();
+    let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form)
+      .await
+      .unwrap();
 
     // Sara creates an application
     let sara_app_form = RegistrationApplicationInsertForm {
@@ -215,9 +229,13 @@ mod tests {
       answer: "LET ME IIIIINN".to_string(),
     };
 
-    let sara_app = RegistrationApplication::create(conn, &sara_app_form).unwrap();
+    let sara_app = RegistrationApplication::create(pool, &sara_app_form)
+      .await
+      .unwrap();
 
-    let read_sara_app_view = RegistrationApplicationView::read(conn, sara_app.id).unwrap();
+    let read_sara_app_view = RegistrationApplicationView::read(pool, sara_app.id)
+      .await
+      .unwrap();
 
     let jess_person_form = PersonInsertForm::builder()
       .name("jess_rav".into())
@@ -225,14 +243,16 @@ mod tests {
       .instance_id(inserted_instance.id)
       .build();
 
-    let inserted_jess_person = Person::create(conn, &jess_person_form).unwrap();
+    let inserted_jess_person = Person::create(pool, &jess_person_form).await.unwrap();
 
     let jess_local_user_form = LocalUserInsertForm::builder()
       .person_id(inserted_jess_person.id)
       .password_encrypted("nada".to_string())
       .build();
 
-    let inserted_jess_local_user = LocalUser::create(conn, &jess_local_user_form).unwrap();
+    let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form)
+      .await
+      .unwrap();
 
     // Sara creates an application
     let jess_app_form = RegistrationApplicationInsertForm {
@@ -240,9 +260,13 @@ mod tests {
       answer: "LET ME IIIIINN".to_string(),
     };
 
-    let jess_app = RegistrationApplication::create(conn, &jess_app_form).unwrap();
+    let jess_app = RegistrationApplication::create(pool, &jess_app_form)
+      .await
+      .unwrap();
 
-    let read_jess_app_view = RegistrationApplicationView::read(conn, jess_app.id).unwrap();
+    let read_jess_app_view = RegistrationApplicationView::read(pool, jess_app.id)
+      .await
+      .unwrap();
 
     let mut expected_sara_app_view = RegistrationApplicationView {
       registration_application: sara_app.to_owned(),
@@ -293,10 +317,11 @@ mod tests {
 
     // Do a batch read of the applications
     let apps = RegistrationApplicationQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .unread_only(Some(true))
       .build()
       .list()
+      .await
       .unwrap();
 
     assert_eq!(
@@ -308,7 +333,9 @@ mod tests {
     );
 
     // Make sure the counts are correct
-    let unread_count = RegistrationApplicationView::get_unread_count(conn, false).unwrap();
+    let unread_count = RegistrationApplicationView::get_unread_count(pool, false)
+      .await
+      .unwrap();
     assert_eq!(unread_count, 2);
 
     // Approve the application
@@ -317,17 +344,22 @@ mod tests {
       deny_reason: None,
     };
 
-    RegistrationApplication::update(conn, sara_app.id, &approve_form).unwrap();
+    RegistrationApplication::update(pool, sara_app.id, &approve_form)
+      .await
+      .unwrap();
 
     // Update the local_user row
     let approve_local_user_form = LocalUserUpdateForm::builder()
       .accepted_application(Some(true))
       .build();
 
-    LocalUser::update(conn, inserted_sara_local_user.id, &approve_local_user_form).unwrap();
+    LocalUser::update(pool, inserted_sara_local_user.id, &approve_local_user_form)
+      .await
+      .unwrap();
 
-    let read_sara_app_view_after_approve =
-      RegistrationApplicationView::read(conn, sara_app.id).unwrap();
+    let read_sara_app_view_after_approve = RegistrationApplicationView::read(pool, sara_app.id)
+      .await
+      .unwrap();
 
     // Make sure the columns changed
     expected_sara_app_view
@@ -361,29 +393,34 @@ mod tests {
     // Do a batch read of apps again
     // It should show only jessicas which is unresolved
     let apps_after_resolve = RegistrationApplicationQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .unread_only(Some(true))
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(apps_after_resolve, vec![read_jess_app_view]);
 
     // Make sure the counts are correct
-    let unread_count_after_approve =
-      RegistrationApplicationView::get_unread_count(conn, false).unwrap();
+    let unread_count_after_approve = RegistrationApplicationView::get_unread_count(pool, false)
+      .await
+      .unwrap();
     assert_eq!(unread_count_after_approve, 1);
 
     // Make sure the not undenied_only has all the apps
     let all_apps = RegistrationApplicationQuery::builder()
-      .conn(conn)
+      .pool(pool)
       .build()
       .list()
+      .await
       .unwrap();
     assert_eq!(all_apps.len(), 2);
 
-    Person::delete(conn, inserted_timmy_person.id).unwrap();
-    Person::delete(conn, inserted_sara_person.id).unwrap();
-    Person::delete(conn, inserted_jess_person.id).unwrap();
-    Instance::delete(conn, inserted_instance.id).unwrap();
+    Person::delete(pool, inserted_timmy_person.id)
+      .await
+      .unwrap();
+    Person::delete(pool, inserted_sara_person.id).await.unwrap();
+    Person::delete(pool, inserted_jess_person.id).await.unwrap();
+    Instance::delete(pool, inserted_instance.id).await.unwrap();
   }
 }
diff --git a/crates/db_views/src/site_view.rs b/crates/db_views/src/site_view.rs
index 10b36ac8..a1d0231a 100644
--- a/crates/db_views/src/site_view.rs
+++ b/crates/db_views/src/site_view.rs
@@ -1,13 +1,16 @@
 use crate::structs::SiteView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, JoinOnDsl, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::SiteAggregates,
   schema::{local_site, local_site_rate_limit, site, site_aggregates},
   source::{local_site::LocalSite, local_site_rate_limit::LocalSiteRateLimit, site::Site},
+  utils::{get_conn, DbPool},
 };
 
 impl SiteView {
-  pub fn read_local(conn: &mut PgConnection) -> Result<Self, Error> {
+  pub async fn read_local(pool: &DbPool) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (mut site, local_site, local_site_rate_limit, counts) = site::table
       .inner_join(local_site::table)
       .inner_join(
@@ -20,7 +23,8 @@ impl SiteView {
         local_site_rate_limit::all_columns,
         site_aggregates::all_columns,
       ))
-      .first::<(Site, LocalSite, LocalSiteRateLimit, SiteAggregates)>(conn)?;
+      .first::<(Site, LocalSite, LocalSiteRateLimit, SiteAggregates)>(conn)
+      .await?;
 
     site.private_key = None;
     Ok(SiteView {
diff --git a/crates/db_views_actor/Cargo.toml b/crates/db_views_actor/Cargo.toml
index e49990ae..ef97f8c1 100644
--- a/crates/db_views_actor/Cargo.toml
+++ b/crates/db_views_actor/Cargo.toml
@@ -12,10 +12,11 @@ rust-version = "1.57"
 doctest = false
 
 [features]
-full = ["lemmy_db_schema/full", "diesel"]
+full = ["lemmy_db_schema/full", "diesel", "diesel-async"]
 
 [dependencies]
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
-diesel = { version = "2.0.0", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
-serde = { version = "1.0.145", features = ["derive"] }
+diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
+diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true }
+serde = { version = "1.0.147", features = ["derive"] }
 typed-builder = "0.10.0"
diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs
index c6794162..73972dee 100644
--- a/crates/db_views_actor/src/comment_reply_view.rs
+++ b/crates/db_views_actor/src/comment_reply_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::CommentReplyView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::CommentAggregates,
   newtypes::{CommentReplyId, PersonId},
@@ -25,7 +34,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::{functions::hot_rank, limit_and_offset},
+  utils::{functions::hot_rank, get_conn, limit_and_offset, DbPool},
   CommentSortType,
 };
 use typed_builder::TypedBuilder;
@@ -46,11 +55,12 @@ type CommentReplyViewTuple = (
 );
 
 impl CommentReplyView {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     comment_reply_id: CommentReplyId,
     my_person_id: Option<PersonId>,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     // The left join below will return None in this case
@@ -131,7 +141,8 @@ impl CommentReplyView {
         person_block::all_columns.nullable(),
         comment_like::score.nullable(),
       ))
-      .first::<CommentReplyViewTuple>(conn)?;
+      .first::<CommentReplyViewTuple>(conn)
+      .await?;
 
     Ok(CommentReplyView {
       comment_reply,
@@ -150,9 +161,11 @@ impl CommentReplyView {
   }
 
   /// Gets the number of unread replies
-  pub fn get_unread_replies(conn: &mut PgConnection, my_person_id: PersonId) -> Result<i64, Error> {
+  pub async fn get_unread_replies(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
     use diesel::dsl::*;
 
+    let conn = &mut get_conn(pool).await?;
+
     comment_reply::table
       .inner_join(comment::table)
       .filter(comment_reply::recipient_id.eq(my_person_id))
@@ -161,6 +174,7 @@ impl CommentReplyView {
       .filter(comment::removed.eq(false))
       .select(count(comment_reply::id))
       .first::<i64>(conn)
+      .await
   }
 }
 
@@ -168,7 +182,7 @@ impl CommentReplyView {
 #[builder(field_defaults(default))]
 pub struct CommentReplyQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   my_person_id: Option<PersonId>,
   recipient_id: Option<PersonId>,
   sort: Option<CommentSortType>,
@@ -179,8 +193,9 @@ pub struct CommentReplyQuery<'a> {
 }
 
 impl<'a> CommentReplyQuery<'a> {
-  pub fn list(self) -> Result<Vec<CommentReplyView>, Error> {
+  pub async fn list(self) -> Result<Vec<CommentReplyView>, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(self.pool).await?;
 
     let person_alias_1 = diesel::alias!(person as person1);
 
@@ -276,7 +291,8 @@ impl<'a> CommentReplyQuery<'a> {
     let res = query
       .limit(limit)
       .offset(offset)
-      .load::<CommentReplyViewTuple>(self.conn)?;
+      .load::<CommentReplyViewTuple>(conn)
+      .await?;
 
     Ok(CommentReplyView::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/community_block_view.rs b/crates/db_views_actor/src/community_block_view.rs
index 6c46904a..2a774b03 100644
--- a/crates/db_views_actor/src/community_block_view.rs
+++ b/crates/db_views_actor/src/community_block_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::CommunityBlockView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, community_block, person},
@@ -8,12 +9,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
+  utils::{get_conn, DbPool},
 };
 
 type CommunityBlockViewTuple = (PersonSafe, CommunitySafe);
 
 impl CommunityBlockView {
-  pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
+  pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_block::table
       .inner_join(person::table)
       .inner_join(community::table)
@@ -25,7 +28,8 @@ impl CommunityBlockView {
       .filter(community::deleted.eq(false))
       .filter(community::removed.eq(false))
       .order_by(community_block::published)
-      .load::<CommunityBlockViewTuple>(conn)?;
+      .load::<CommunityBlockViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/community_follower_view.rs b/crates/db_views_actor/src/community_follower_view.rs
index 51e58fda..3b03b027 100644
--- a/crates/db_views_actor/src/community_follower_view.rs
+++ b/crates/db_views_actor/src/community_follower_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::CommunityFollowerView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::{CommunityId, PersonId},
   schema::{community, community_follower, person},
@@ -8,15 +9,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
+  utils::{get_conn, DbPool},
 };
 
 type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe);
 
 impl CommunityFollowerView {
-  pub fn for_community(
-    conn: &mut PgConnection,
-    community_id: CommunityId,
-  ) -> Result<Vec<Self>, Error> {
+  pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_follower::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -26,12 +26,14 @@ impl CommunityFollowerView {
       ))
       .filter(community_follower::community_id.eq(community_id))
       .order_by(community::title)
-      .load::<CommunityFollowerViewTuple>(conn)?;
+      .load::<CommunityFollowerViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
 
-  pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
+  pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_follower::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -43,7 +45,8 @@ impl CommunityFollowerView {
       .filter(community::deleted.eq(false))
       .filter(community::removed.eq(false))
       .order_by(community::title)
-      .load::<CommunityFollowerViewTuple>(conn)?;
+      .load::<CommunityFollowerViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs
index 28ad6d84..e9e6625c 100644
--- a/crates/db_views_actor/src/community_moderator_view.rs
+++ b/crates/db_views_actor/src/community_moderator_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::CommunityModeratorView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::{CommunityId, PersonId},
   schema::{community, community_moderator, person},
@@ -8,15 +9,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
+  utils::{get_conn, DbPool},
 };
 
 type CommunityModeratorViewTuple = (CommunitySafe, PersonSafe);
 
 impl CommunityModeratorView {
-  pub fn for_community(
-    conn: &mut PgConnection,
-    community_id: CommunityId,
-  ) -> Result<Vec<Self>, Error> {
+  pub async fn for_community(pool: &DbPool, community_id: CommunityId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_moderator::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -26,12 +26,14 @@ impl CommunityModeratorView {
       ))
       .filter(community_moderator::community_id.eq(community_id))
       .order_by(community_moderator::published)
-      .load::<CommunityModeratorViewTuple>(conn)?;
+      .load::<CommunityModeratorViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
 
-  pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
+  pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_moderator::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -43,14 +45,16 @@ impl CommunityModeratorView {
       .filter(community::deleted.eq(false))
       .filter(community::removed.eq(false))
       .order_by(community_moderator::published)
-      .load::<CommunityModeratorViewTuple>(conn)?;
+      .load::<CommunityModeratorViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
 
   /// Finds all communities first mods / creators
   /// Ideally this should be a group by, but diesel doesn't support it yet
-  pub fn get_community_first_mods(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
+  pub async fn get_community_first_mods(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let res = community_moderator::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -65,7 +69,8 @@ impl CommunityModeratorView {
         community_moderator::community_id,
         community_moderator::person_id,
       ))
-      .load::<CommunityModeratorViewTuple>(conn)?;
+      .load::<CommunityModeratorViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/community_person_ban_view.rs b/crates/db_views_actor/src/community_person_ban_view.rs
index 8672ad21..ff7f26c9 100644
--- a/crates/db_views_actor/src/community_person_ban_view.rs
+++ b/crates/db_views_actor/src/community_person_ban_view.rs
@@ -1,5 +1,6 @@
 use crate::structs::CommunityPersonBanView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{dsl::*, result::Error, BoolExpressionMethods, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::{CommunityId, PersonId},
   schema::{community, community_person_ban, person},
@@ -8,14 +9,16 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::ToSafe,
+  utils::{get_conn, DbPool},
 };
 
 impl CommunityPersonBanView {
-  pub fn get(
-    conn: &mut PgConnection,
+  pub async fn get(
+    pool: &DbPool,
     from_person_id: PersonId,
     from_community_id: CommunityId,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (community, person) = community_person_ban::table
       .inner_join(community::table)
       .inner_join(person::table)
@@ -31,7 +34,8 @@ impl CommunityPersonBanView {
           .or(community_person_ban::expires.gt(now)),
       )
       .order_by(community_person_ban::published)
-      .first::<(CommunitySafe, PersonSafe)>(conn)?;
+      .first::<(CommunitySafe, PersonSafe)>(conn)
+      .await?;
 
     Ok(CommunityPersonBanView { community, person })
   }
diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs
index 5a65b887..f27c58c8 100644
--- a/crates/db_views_actor/src/community_view.rs
+++ b/crates/db_views_actor/src/community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{CommunityModeratorView, CommunityView, PersonViewSafe};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  PgTextExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::CommunityAggregates,
   newtypes::{CommunityId, PersonId},
@@ -10,7 +19,7 @@ use lemmy_db_schema::{
     local_user::LocalUser,
   },
   traits::{ToSafe, ViewToVec},
-  utils::{functions::hot_rank, fuzzy_search, limit_and_offset},
+  utils::{functions::hot_rank, fuzzy_search, get_conn, limit_and_offset, DbPool},
   ListingType,
   SortType,
 };
@@ -24,11 +33,12 @@ type CommunityViewTuple = (
 );
 
 impl CommunityView {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     community_id: CommunityId,
     my_person_id: Option<PersonId>,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     // The left join below will return None in this case
     let person_id_join = my_person_id.unwrap_or(PersonId(-1));
 
@@ -55,7 +65,8 @@ impl CommunityView {
         community_follower::all_columns.nullable(),
         community_block::all_columns.nullable(),
       ))
-      .first::<CommunityViewTuple>(conn)?;
+      .first::<CommunityViewTuple>(conn)
+      .await?;
 
     Ok(CommunityView {
       community,
@@ -65,12 +76,13 @@ impl CommunityView {
     })
   }
 
-  pub fn is_mod_or_admin(
-    conn: &mut PgConnection,
+  pub async fn is_mod_or_admin(
+    pool: &DbPool,
     person_id: PersonId,
     community_id: CommunityId,
-  ) -> bool {
-    let is_mod = CommunityModeratorView::for_community(conn, community_id)
+  ) -> Result<bool, Error> {
+    let is_mod = CommunityModeratorView::for_community(pool, community_id)
+      .await
       .map(|v| {
         v.into_iter()
           .map(|m| m.moderator.id)
@@ -79,17 +91,19 @@ impl CommunityView {
       .unwrap_or_default()
       .contains(&person_id);
     if is_mod {
-      return true;
+      return Ok(true);
     }
 
-    PersonViewSafe::admins(conn)
+    let is_admin = PersonViewSafe::admins(pool)
+      .await
       .map(|v| {
         v.into_iter()
           .map(|a| a.person.id)
           .collect::<Vec<PersonId>>()
       })
       .unwrap_or_default()
-      .contains(&person_id)
+      .contains(&person_id);
+    Ok(is_admin)
   }
 }
 
@@ -97,7 +111,7 @@ impl CommunityView {
 #[builder(field_defaults(default))]
 pub struct CommunityQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   listing_type: Option<ListingType>,
   sort: Option<SortType>,
   local_user: Option<&'a LocalUser>,
@@ -107,7 +121,9 @@ pub struct CommunityQuery<'a> {
 }
 
 impl<'a> CommunityQuery<'a> {
-  pub fn list(self) -> Result<Vec<CommunityView>, Error> {
+  pub async fn list(self) -> Result<Vec<CommunityView>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
+
     // The left join below will return None in this case
     let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
 
@@ -203,7 +219,8 @@ impl<'a> CommunityQuery<'a> {
       .offset(offset)
       .filter(community::removed.eq(false))
       .filter(community::deleted.eq(false))
-      .load::<CommunityViewTuple>(self.conn)?;
+      .load::<CommunityViewTuple>(conn)
+      .await?;
 
     Ok(CommunityView::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/person_block_view.rs b/crates/db_views_actor/src/person_block_view.rs
index b8bb09fe..5ece0439 100644
--- a/crates/db_views_actor/src/person_block_view.rs
+++ b/crates/db_views_actor/src/person_block_view.rs
@@ -1,16 +1,19 @@
 use crate::structs::PersonBlockView;
-use diesel::{result::Error, *};
+use diesel::{result::Error, ExpressionMethods, QueryDsl};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{person, person_block},
   source::person::{Person, PersonSafe},
   traits::{ToSafe, ViewToVec},
+  utils::{get_conn, DbPool},
 };
 
 type PersonBlockViewTuple = (PersonSafe, PersonSafe);
 
 impl PersonBlockView {
-  pub fn for_person(conn: &mut PgConnection, person_id: PersonId) -> Result<Vec<Self>, Error> {
+  pub async fn for_person(pool: &DbPool, person_id: PersonId) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     let res = person_block::table
@@ -23,7 +26,8 @@ impl PersonBlockView {
       .filter(person_block::person_id.eq(person_id))
       .filter(person_alias_1.field(person::deleted).eq(false))
       .order_by(person_block::published)
-      .load::<PersonBlockViewTuple>(conn)?;
+      .load::<PersonBlockViewTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs
index 2b6daf5d..3930382a 100644
--- a/crates/db_views_actor/src/person_mention_view.rs
+++ b/crates/db_views_actor/src/person_mention_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::PersonMentionView;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::CommentAggregates,
   newtypes::{PersonId, PersonMentionId},
@@ -25,7 +34,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::{functions::hot_rank, limit_and_offset},
+  utils::{functions::hot_rank, get_conn, limit_and_offset, DbPool},
   CommentSortType,
 };
 use typed_builder::TypedBuilder;
@@ -46,11 +55,12 @@ type PersonMentionViewTuple = (
 );
 
 impl PersonMentionView {
-  pub fn read(
-    conn: &mut PgConnection,
+  pub async fn read(
+    pool: &DbPool,
     person_mention_id: PersonMentionId,
     my_person_id: Option<PersonId>,
   ) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
 
     // The left join below will return None in this case
@@ -131,7 +141,8 @@ impl PersonMentionView {
         person_block::all_columns.nullable(),
         comment_like::score.nullable(),
       ))
-      .first::<PersonMentionViewTuple>(conn)?;
+      .first::<PersonMentionViewTuple>(conn)
+      .await?;
 
     Ok(PersonMentionView {
       person_mention,
@@ -150,11 +161,9 @@ impl PersonMentionView {
   }
 
   /// Gets the number of unread mentions
-  pub fn get_unread_mentions(
-    conn: &mut PgConnection,
-    my_person_id: PersonId,
-  ) -> Result<i64, Error> {
+  pub async fn get_unread_mentions(pool: &DbPool, my_person_id: PersonId) -> Result<i64, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(pool).await?;
 
     person_mention::table
       .inner_join(comment::table)
@@ -164,6 +173,7 @@ impl PersonMentionView {
       .filter(comment::removed.eq(false))
       .select(count(person_mention::id))
       .first::<i64>(conn)
+      .await
   }
 }
 
@@ -171,7 +181,7 @@ impl PersonMentionView {
 #[builder(field_defaults(default))]
 pub struct PersonMentionQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   my_person_id: Option<PersonId>,
   recipient_id: Option<PersonId>,
   sort: Option<CommentSortType>,
@@ -182,8 +192,9 @@ pub struct PersonMentionQuery<'a> {
 }
 
 impl<'a> PersonMentionQuery<'a> {
-  pub fn list(self) -> Result<Vec<PersonMentionView>, Error> {
+  pub async fn list(self) -> Result<Vec<PersonMentionView>, Error> {
     use diesel::dsl::*;
+    let conn = &mut get_conn(self.pool).await?;
 
     let person_alias_1 = diesel::alias!(person as person1);
 
@@ -279,7 +290,8 @@ impl<'a> PersonMentionQuery<'a> {
     let res = query
       .limit(limit)
       .offset(offset)
-      .load::<PersonMentionViewTuple>(self.conn)?;
+      .load::<PersonMentionViewTuple>(conn)
+      .await?;
 
     Ok(PersonMentionView::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs
index 55a64819..cbacb8e5 100644
--- a/crates/db_views_actor/src/person_view.rs
+++ b/crates/db_views_actor/src/person_view.rs
@@ -1,41 +1,55 @@
 use crate::structs::PersonViewSafe;
-use diesel::{dsl::*, result::Error, *};
+use diesel::{
+  dsl::*,
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  PgTextExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   aggregates::structs::PersonAggregates,
   newtypes::PersonId,
   schema::{person, person_aggregates},
   source::person::{Person, PersonSafe},
   traits::{ToSafe, ViewToVec},
-  utils::{fuzzy_search, limit_and_offset},
+  utils::{fuzzy_search, get_conn, limit_and_offset, DbPool},
   SortType,
 };
+use std::iter::Iterator;
 use typed_builder::TypedBuilder;
 
 type PersonViewSafeTuple = (PersonSafe, PersonAggregates);
 
 impl PersonViewSafe {
-  pub fn read(conn: &mut PgConnection, person_id: PersonId) -> Result<Self, Error> {
+  pub async fn read(pool: &DbPool, person_id: PersonId) -> Result<Self, Error> {
+    let conn = &mut get_conn(pool).await?;
     let (person, counts) = person::table
       .find(person_id)
       .inner_join(person_aggregates::table)
       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
-      .first::<PersonViewSafeTuple>(conn)?;
+      .first::<PersonViewSafeTuple>(conn)
+      .await?;
     Ok(Self { person, counts })
   }
 
-  pub fn admins(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
+  pub async fn admins(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let admins = person::table
       .inner_join(person_aggregates::table)
       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
       .filter(person::admin.eq(true))
       .filter(person::deleted.eq(false))
       .order_by(person::published)
-      .load::<PersonViewSafeTuple>(conn)?;
+      .load::<PersonViewSafeTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(admins))
   }
 
-  pub fn banned(conn: &mut PgConnection) -> Result<Vec<Self>, Error> {
+  pub async fn banned(pool: &DbPool) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let banned = person::table
       .inner_join(person_aggregates::table)
       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
@@ -47,7 +61,8 @@ impl PersonViewSafe {
         ),
       )
       .filter(person::deleted.eq(false))
-      .load::<PersonViewSafeTuple>(conn)?;
+      .load::<PersonViewSafeTuple>(conn)
+      .await?;
 
     Ok(Self::from_tuple_to_vec(banned))
   }
@@ -57,7 +72,7 @@ impl PersonViewSafe {
 #[builder(field_defaults(default))]
 pub struct PersonQuery<'a> {
   #[builder(!default)]
-  conn: &'a mut PgConnection,
+  pool: &'a DbPool,
   sort: Option<SortType>,
   search_term: Option<String>,
   page: Option<i64>,
@@ -65,7 +80,8 @@ pub struct PersonQuery<'a> {
 }
 
 impl<'a> PersonQuery<'a> {
-  pub fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
+  pub async fn list(self) -> Result<Vec<PersonViewSafe>, Error> {
+    let conn = &mut get_conn(self.pool).await?;
     let mut query = person::table
       .inner_join(person_aggregates::table)
       .select((Person::safe_columns_tuple(), person_aggregates::all_columns))
@@ -107,7 +123,7 @@ impl<'a> PersonQuery<'a> {
     let (limit, offset) = limit_and_offset(self.page, self.limit)?;
     query = query.limit(limit).offset(offset);
 
-    let res = query.load::<PersonViewSafeTuple>(self.conn)?;
+    let res = query.load::<PersonViewSafeTuple>(conn).await?;
 
     Ok(PersonViewSafe::from_tuple_to_vec(res))
   }
diff --git a/crates/db_views_moderator/Cargo.toml b/crates/db_views_moderator/Cargo.toml
index e2823993..c568dae0 100644
--- a/crates/db_views_moderator/Cargo.toml
+++ b/crates/db_views_moderator/Cargo.toml
@@ -12,9 +12,10 @@ rust-version = "1.57"
 doctest = false
 
 [features]
-full = ["lemmy_db_schema/full", "diesel"]
+full = ["lemmy_db_schema/full", "diesel", "diesel-async"]
 
 [dependencies]
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
-diesel = { version = "2.0.0", features = ["postgres","chrono","r2d2","serde_json"], optional = true }
-serde = { version = "1.0.145", features = ["derive"] }
+diesel = { version = "2.0.2", features = ["postgres","chrono","serde_json"], optional = true }
+diesel-async = { version = "0.1.1", features = ["postgres", "bb8"], optional = true }
+serde = { version = "1.0.147", features = ["derive"] }
diff --git a/crates/db_views_moderator/src/admin_purge_comment_view.rs b/crates/db_views_moderator/src/admin_purge_comment_view.rs
index 035f86d1..d9edaa10 100644
--- a/crates/db_views_moderator/src/admin_purge_comment_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_comment_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{AdminPurgeCommentView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{admin_purge_comment, person, post},
@@ -9,13 +18,14 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type AdminPurgeCommentViewTuple = (AdminPurgeComment, Option<PersonSafe>, Post);
 
 impl AdminPurgeCommentView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -44,7 +54,8 @@ impl AdminPurgeCommentView {
       .limit(limit)
       .offset(offset)
       .order_by(admin_purge_comment::when_.desc())
-      .load::<AdminPurgeCommentViewTuple>(conn)?;
+      .load::<AdminPurgeCommentViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/admin_purge_community_view.rs b/crates/db_views_moderator/src/admin_purge_community_view.rs
index fb582d6d..501013d0 100644
--- a/crates/db_views_moderator/src/admin_purge_community_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{AdminPurgeCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{admin_purge_community, person},
@@ -8,13 +17,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type AdminPurgeCommunityViewTuple = (AdminPurgeCommunity, Option<PersonSafe>);
 
 impl AdminPurgeCommunityView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -41,7 +51,8 @@ impl AdminPurgeCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(admin_purge_community::when_.desc())
-      .load::<AdminPurgeCommunityViewTuple>(conn)?;
+      .load::<AdminPurgeCommunityViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/admin_purge_person_view.rs b/crates/db_views_moderator/src/admin_purge_person_view.rs
index 023bcb37..a0abe0ca 100644
--- a/crates/db_views_moderator/src/admin_purge_person_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_person_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{AdminPurgePersonView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{admin_purge_person, person},
@@ -8,13 +17,15 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type AdminPurgePersonViewTuple = (AdminPurgePerson, Option<PersonSafe>);
 
 impl AdminPurgePersonView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -40,7 +51,8 @@ impl AdminPurgePersonView {
       .limit(limit)
       .offset(offset)
       .order_by(admin_purge_person::when_.desc())
-      .load::<AdminPurgePersonViewTuple>(conn)?;
+      .load::<AdminPurgePersonViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/admin_purge_post_view.rs b/crates/db_views_moderator/src/admin_purge_post_view.rs
index 6a65c7a4..38cb6b5e 100644
--- a/crates/db_views_moderator/src/admin_purge_post_view.rs
+++ b/crates/db_views_moderator/src/admin_purge_post_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{AdminPurgePostView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{admin_purge_post, community, person},
@@ -9,13 +18,15 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type AdminPurgePostViewTuple = (AdminPurgePost, Option<PersonSafe>, CommunitySafe);
 
 impl AdminPurgePostView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -43,7 +54,8 @@ impl AdminPurgePostView {
       .limit(limit)
       .offset(offset)
       .order_by(admin_purge_post::when_.desc())
-      .load::<AdminPurgePostViewTuple>(conn)?;
+      .load::<AdminPurgePostViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_add_community_view.rs b/crates/db_views_moderator/src/mod_add_community_view.rs
index b7b9e93a..bad3a1de 100644
--- a/crates/db_views_moderator/src/mod_add_community_view.rs
+++ b/crates/db_views_moderator/src/mod_add_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModAddCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_add_community, person},
@@ -9,7 +18,7 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModAddCommunityViewTuple = (
@@ -20,7 +29,8 @@ type ModAddCommunityViewTuple = (
 );
 
 impl ModAddCommunityView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -61,7 +71,8 @@ impl ModAddCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_add_community::when_.desc())
-      .load::<ModAddCommunityViewTuple>(conn)?;
+      .load::<ModAddCommunityViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_add_view.rs b/crates/db_views_moderator/src/mod_add_view.rs
index e7155250..3fc4b35b 100644
--- a/crates/db_views_moderator/src/mod_add_view.rs
+++ b/crates/db_views_moderator/src/mod_add_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModAddView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{mod_add, person},
@@ -8,13 +17,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModAddViewTuple = (ModAdd, Option<PersonSafe>, PersonSafe);
 
 impl ModAddView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -47,7 +57,8 @@ impl ModAddView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_add::when_.desc())
-      .load::<ModAddViewTuple>(conn)?;
+      .load::<ModAddViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_ban_from_community_view.rs b/crates/db_views_moderator/src/mod_ban_from_community_view.rs
index bf885dbc..cf10c53a 100644
--- a/crates/db_views_moderator/src/mod_ban_from_community_view.rs
+++ b/crates/db_views_moderator/src/mod_ban_from_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModBanFromCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_ban_from_community, person},
@@ -9,7 +18,7 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModBanFromCommunityViewTuple = (
@@ -20,7 +29,9 @@ type ModBanFromCommunityViewTuple = (
 );
 
 impl ModBanFromCommunityView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -62,7 +73,8 @@ impl ModBanFromCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_ban_from_community::when_.desc())
-      .load::<ModBanFromCommunityViewTuple>(conn)?;
+      .load::<ModBanFromCommunityViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_ban_view.rs b/crates/db_views_moderator/src/mod_ban_view.rs
index 94bfbc8d..adb0623c 100644
--- a/crates/db_views_moderator/src/mod_ban_view.rs
+++ b/crates/db_views_moderator/src/mod_ban_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModBanView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{mod_ban, person},
@@ -8,13 +17,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModBanViewTuple = (ModBan, Option<PersonSafe>, PersonSafe);
 
 impl ModBanView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -47,7 +57,8 @@ impl ModBanView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_ban::when_.desc())
-      .load::<ModBanViewTuple>(conn)?;
+      .load::<ModBanViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_hide_community_view.rs b/crates/db_views_moderator/src/mod_hide_community_view.rs
index 0250d2e7..4b382d51 100644
--- a/crates/db_views_moderator/src/mod_hide_community_view.rs
+++ b/crates/db_views_moderator/src/mod_hide_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModHideCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_hide_community, person},
@@ -9,14 +18,16 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModHideCommunityViewTuple = (ModHideCommunity, Option<PersonSafe>, CommunitySafe);
 
 impl ModHideCommunityView {
   // Pass in mod_id as admin_id because only admins can do this action
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -48,7 +59,8 @@ impl ModHideCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_hide_community::when_.desc())
-      .load::<ModHideCommunityViewTuple>(conn)?;
+      .load::<ModHideCommunityViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_lock_post_view.rs b/crates/db_views_moderator/src/mod_lock_post_view.rs
index 6d88c5ae..27758446 100644
--- a/crates/db_views_moderator/src/mod_lock_post_view.rs
+++ b/crates/db_views_moderator/src/mod_lock_post_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModLockPostView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_lock_post, person, post},
@@ -10,13 +19,15 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModLockPostViewTuple = (ModLockPost, Option<PersonSafe>, Post, CommunitySafe);
 
 impl ModLockPostView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -56,7 +67,8 @@ impl ModLockPostView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_lock_post::when_.desc())
-      .load::<ModLockPostViewTuple>(conn)?;
+      .load::<ModLockPostViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_remove_comment_view.rs b/crates/db_views_moderator/src/mod_remove_comment_view.rs
index c0b58845..52eb8e75 100644
--- a/crates/db_views_moderator/src/mod_remove_comment_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_comment_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModRemoveCommentView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{comment, community, mod_remove_comment, person, post},
@@ -11,7 +20,7 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModRemoveCommentViewTuple = (
@@ -24,7 +33,8 @@ type ModRemoveCommentViewTuple = (
 );
 
 impl ModRemoveCommentView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(lemmy_db_schema::schema::person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -67,7 +77,8 @@ impl ModRemoveCommentView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_remove_comment::when_.desc())
-      .load::<ModRemoveCommentViewTuple>(conn)?;
+      .load::<ModRemoveCommentViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_remove_community_view.rs b/crates/db_views_moderator/src/mod_remove_community_view.rs
index ffd62d45..293b8455 100644
--- a/crates/db_views_moderator/src/mod_remove_community_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModRemoveCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_remove_community, person},
@@ -9,13 +18,14 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModRemoveCommunityTuple = (ModRemoveCommunity, Option<PersonSafe>, CommunitySafe);
 
 impl ModRemoveCommunityView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
     let show_mod_names_expr = show_mod_names.as_sql::<diesel::sql_types::Bool>();
@@ -43,7 +53,8 @@ impl ModRemoveCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_remove_community::when_.desc())
-      .load::<ModRemoveCommunityTuple>(conn)?;
+      .load::<ModRemoveCommunityTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_remove_post_view.rs b/crates/db_views_moderator/src/mod_remove_post_view.rs
index c1bc2e8f..20d5b09b 100644
--- a/crates/db_views_moderator/src/mod_remove_post_view.rs
+++ b/crates/db_views_moderator/src/mod_remove_post_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModRemovePostView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_remove_post, person, post},
@@ -10,13 +19,15 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModRemovePostViewTuple = (ModRemovePost, Option<PersonSafe>, Post, CommunitySafe);
 
 impl ModRemovePostView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -56,7 +67,8 @@ impl ModRemovePostView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_remove_post::when_.desc())
-      .load::<ModRemovePostViewTuple>(conn)?;
+      .load::<ModRemovePostViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_sticky_post_view.rs b/crates/db_views_moderator/src/mod_sticky_post_view.rs
index d802de69..28736292 100644
--- a/crates/db_views_moderator/src/mod_sticky_post_view.rs
+++ b/crates/db_views_moderator/src/mod_sticky_post_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModStickyPostView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_sticky_post, person, post},
@@ -10,13 +19,14 @@ use lemmy_db_schema::{
     post::Post,
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModStickyPostViewTuple = (ModStickyPost, Option<PersonSafe>, Post, CommunitySafe);
 
 impl ModStickyPostView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -56,7 +66,8 @@ impl ModStickyPostView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_sticky_post::when_.desc())
-      .load::<ModStickyPostViewTuple>(conn)?;
+      .load::<ModStickyPostViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/db_views_moderator/src/mod_transfer_community_view.rs b/crates/db_views_moderator/src/mod_transfer_community_view.rs
index bea839eb..182558a4 100644
--- a/crates/db_views_moderator/src/mod_transfer_community_view.rs
+++ b/crates/db_views_moderator/src/mod_transfer_community_view.rs
@@ -1,5 +1,14 @@
 use crate::structs::{ModTransferCommunityView, ModlogListParams};
-use diesel::{result::Error, *};
+use diesel::{
+  result::Error,
+  BoolExpressionMethods,
+  ExpressionMethods,
+  IntoSql,
+  JoinOnDsl,
+  NullableExpressionMethods,
+  QueryDsl,
+};
+use diesel_async::RunQueryDsl;
 use lemmy_db_schema::{
   newtypes::PersonId,
   schema::{community, mod_transfer_community, person},
@@ -9,7 +18,7 @@ use lemmy_db_schema::{
     person::{Person, PersonSafe},
   },
   traits::{ToSafe, ViewToVec},
-  utils::limit_and_offset,
+  utils::{get_conn, limit_and_offset, DbPool},
 };
 
 type ModTransferCommunityViewTuple = (
@@ -20,7 +29,9 @@ type ModTransferCommunityViewTuple = (
 );
 
 impl ModTransferCommunityView {
-  pub fn list(conn: &mut PgConnection, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+  pub async fn list(pool: &DbPool, params: ModlogListParams) -> Result<Vec<Self>, Error> {
+    let conn = &mut get_conn(pool).await?;
+
     let person_alias_1 = diesel::alias!(person as person1);
     let admin_person_id_join = params.mod_person_id.unwrap_or(PersonId(-1));
     let show_mod_names = !params.hide_modlog_names;
@@ -62,7 +73,8 @@ impl ModTransferCommunityView {
       .limit(limit)
       .offset(offset)
       .order_by(mod_transfer_community::when_.desc())
-      .load::<ModTransferCommunityViewTuple>(conn)?;
+      .load::<ModTransferCommunityViewTuple>(conn)
+      .await?;
 
     let results = Self::from_tuple_to_vec(res);
     Ok(results)
diff --git a/crates/routes/Cargo.toml b/crates/routes/Cargo.toml
index bda019d3..1186a6b9 100644
--- a/crates/routes/Cargo.toml
+++ b/crates/routes/Cargo.toml
@@ -19,17 +19,17 @@ lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor" }
 lemmy_db_schema = { version = "=0.16.5", path = "../db_schema" }
 lemmy_api_common = { version = "=0.16.5", path = "../api_common" }
 lemmy_apub = { version = "=0.16.5", path = "../apub" }
-diesel = "2.0.0"
+diesel = "2.0.2"
 actix-web = { version = "4.2.1", default-features = false, features = ["rustls"] }
-anyhow = "1.0.65"
+anyhow = "1.0.66"
 chrono = { version = "0.4.22", features = ["serde"], default-features = false }
-futures = "0.3.24"
+futures = "0.3.25"
 reqwest = { version = "0.11.12", features = ["stream"] }
 reqwest-middleware = "0.1.6"
 rss = "2.0.1"
-serde = { version = "1.0.145", features = ["derive"] }
+serde = { version = "1.0.147", features = ["derive"] }
 url = { version = "2.3.1", features = ["serde"] }
 strum = "0.24.1"
 once_cell = "1.15.0"
 tracing = "0.1.36"
-tokio = { version = "1.21.1", features = ["sync"] }
+tokio = { version = "1.21.2", features = ["sync"] }
diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs
index 1943c280..cb4fb918 100644
--- a/crates/routes/src/feeds.rs
+++ b/crates/routes/src/feeds.rs
@@ -1,12 +1,11 @@
 use actix_web::{error::ErrorBadRequest, *};
 use anyhow::anyhow;
 use chrono::{DateTime, NaiveDateTime, Utc};
-use diesel::PgConnection;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_schema::{
   newtypes::LocalUserId,
   source::{community::Community, local_user::LocalUser, person::Person},
   traits::{ApubActor, Crud},
+  utils::DbPool,
   CommentSortType,
   ListingType,
   SortType,
@@ -88,18 +87,16 @@ async fn get_feed_data(
   listing_type: ListingType,
   sort_type: SortType,
 ) -> Result<HttpResponse, LemmyError> {
-  let site_view = blocking(context.pool(), SiteView::read_local).await??;
-
-  let posts = blocking(context.pool(), move |conn| {
-    PostQuery::builder()
-      .conn(conn)
-      .listing_type(Some(listing_type))
-      .sort(Some(sort_type))
-      .limit(Some(RSS_FETCH_LIMIT))
-      .build()
-      .list()
-  })
-  .await??;
+  let site_view = SiteView::read_local(context.pool()).await?;
+
+  let posts = PostQuery::builder()
+    .pool(context.pool())
+    .listing_type(Some(listing_type))
+    .sort(Some(sort_type))
+    .limit(Some(RSS_FETCH_LIMIT))
+    .build()
+    .list()
+    .await?;
 
   let items = create_post_items(posts, &context.settings().get_protocol_and_hostname())?;
 
@@ -144,19 +141,27 @@ async fn get_feed(
   let jwt_secret = context.secret().jwt_secret.to_owned();
   let protocol_and_hostname = context.settings().get_protocol_and_hostname();
 
-  let builder = blocking(context.pool(), move |conn| match request_type {
-    RequestType::User => get_feed_user(conn, &sort_type, &param, &protocol_and_hostname),
-    RequestType::Community => get_feed_community(conn, &sort_type, &param, &protocol_and_hostname),
-    RequestType::Front => get_feed_front(
-      conn,
-      &jwt_secret,
-      &sort_type,
-      &param,
-      &protocol_and_hostname,
-    ),
-    RequestType::Inbox => get_feed_inbox(conn, &jwt_secret, &param, &protocol_and_hostname),
-  })
-  .await?
+  let builder = match request_type {
+    RequestType::User => {
+      get_feed_user(context.pool(), &sort_type, &param, &protocol_and_hostname).await
+    }
+    RequestType::Community => {
+      get_feed_community(context.pool(), &sort_type, &param, &protocol_and_hostname).await
+    }
+    RequestType::Front => {
+      get_feed_front(
+        context.pool(),
+        &jwt_secret,
+        &sort_type,
+        &param,
+        &protocol_and_hostname,
+      )
+      .await
+    }
+    RequestType::Inbox => {
+      get_feed_inbox(context.pool(), &jwt_secret, &param, &protocol_and_hostname).await
+    }
+  }
   .map_err(ErrorBadRequest)?;
 
   let rss = builder.build().to_string();
@@ -177,23 +182,24 @@ fn get_sort_type(info: web::Query<Params>) -> Result<SortType, ParseError> {
 }
 
 #[tracing::instrument(skip_all)]
-fn get_feed_user(
-  conn: &mut PgConnection,
+async fn get_feed_user(
+  pool: &DbPool,
   sort_type: &SortType,
   user_name: &str,
   protocol_and_hostname: &str,
 ) -> Result<ChannelBuilder, LemmyError> {
-  let site_view = SiteView::read_local(conn)?;
-  let person = Person::read_from_name(conn, user_name, false)?;
+  let site_view = SiteView::read_local(pool).await?;
+  let person = Person::read_from_name(pool, user_name, false).await?;
 
   let posts = PostQuery::builder()
-    .conn(conn)
+    .pool(pool)
     .listing_type(Some(ListingType::All))
     .sort(Some(*sort_type))
     .creator_id(Some(person.id))
     .limit(Some(RSS_FETCH_LIMIT))
     .build()
-    .list()?;
+    .list()
+    .await?;
 
   let items = create_post_items(posts, protocol_and_hostname)?;
 
@@ -208,22 +214,23 @@ fn get_feed_user(
 }
 
 #[tracing::instrument(skip_all)]
-fn get_feed_community(
-  conn: &mut PgConnection,
+async fn get_feed_community(
+  pool: &DbPool,
   sort_type: &SortType,
   community_name: &str,
   protocol_and_hostname: &str,
 ) -> Result<ChannelBuilder, LemmyError> {
-  let site_view = SiteView::read_local(conn)?;
-  let community = Community::read_from_name(conn, community_name, false)?;
+  let site_view = SiteView::read_local(pool).await?;
+  let community = Community::read_from_name(pool, community_name, false).await?;
 
   let posts = PostQuery::builder()
-    .conn(conn)
+    .pool(pool)
     .sort(Some(*sort_type))
     .community_id(Some(community.id))
     .limit(Some(RSS_FETCH_LIMIT))
     .build()
-    .list()?;
+    .list()
+    .await?;
 
   let items = create_post_items(posts, protocol_and_hostname)?;
 
@@ -242,25 +249,26 @@ fn get_feed_community(
 }
 
 #[tracing::instrument(skip_all)]
-fn get_feed_front(
-  conn: &mut PgConnection,
+async fn get_feed_front(
+  pool: &DbPool,
   jwt_secret: &str,
   sort_type: &SortType,
   jwt: &str,
   protocol_and_hostname: &str,
 ) -> Result<ChannelBuilder, LemmyError> {
-  let site_view = SiteView::read_local(conn)?;
+  let site_view = SiteView::read_local(pool).await?;
   let local_user_id = LocalUserId(Claims::decode(jwt, jwt_secret)?.claims.sub);
-  let local_user = LocalUser::read(conn, local_user_id)?;
+  let local_user = LocalUser::read(pool, local_user_id).await?;
 
   let posts = PostQuery::builder()
-    .conn(conn)
+    .pool(pool)
     .listing_type(Some(ListingType::Subscribed))
     .local_user(Some(&local_user))
     .sort(Some(*sort_type))
     .limit(Some(RSS_FETCH_LIMIT))
     .build()
-    .list()?;
+    .list()
+    .await?;
 
   let items = create_post_items(posts, protocol_and_hostname)?;
 
@@ -279,39 +287,41 @@ fn get_feed_front(
 }
 
 #[tracing::instrument(skip_all)]
-fn get_feed_inbox(
-  conn: &mut PgConnection,
+async fn get_feed_inbox(
+  pool: &DbPool,
   jwt_secret: &str,
   jwt: &str,
   protocol_and_hostname: &str,
 ) -> Result<ChannelBuilder, LemmyError> {
-  let site_view = SiteView::read_local(conn)?;
+  let site_view = SiteView::read_local(pool).await?;
   let local_user_id = LocalUserId(Claims::decode(jwt, jwt_secret)?.claims.sub);
-  let local_user = LocalUser::read(conn, local_user_id)?;
+  let local_user = LocalUser::read(pool, local_user_id).await?;
   let person_id = local_user.person_id;
   let show_bot_accounts = local_user.show_bot_accounts;
 
   let sort = CommentSortType::New;
 
   let replies = CommentReplyQuery::builder()
-    .conn(conn)
+    .pool(pool)
     .recipient_id(Some(person_id))
     .my_person_id(Some(person_id))
     .show_bot_accounts(Some(show_bot_accounts))
     .sort(Some(sort))
     .limit(Some(RSS_FETCH_LIMIT))
     .build()
-    .list()?;
+    .list()
+    .await?;
 
   let mentions = PersonMentionQuery::builder()
-    .conn(conn)
+    .pool(pool)
     .recipient_id(Some(person_id))
     .my_person_id(Some(person_id))
     .show_bot_accounts(Some(show_bot_accounts))
     .sort(Some(sort))
     .limit(Some(RSS_FETCH_LIMIT))
     .build()
-    .list()?;
+    .list()
+    .await?;
 
   let items = create_reply_and_mention_items(replies, mentions, protocol_and_hostname)?;
 
diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs
index 59a55fde..97134078 100644
--- a/crates/routes/src/images.rs
+++ b/crates/routes/src/images.rs
@@ -11,7 +11,7 @@ use actix_web::{
   HttpResponse,
 };
 use futures::stream::{Stream, StreamExt};
-use lemmy_api_common::utils::{blocking, get_local_user_view_from_jwt};
+use lemmy_api_common::utils::get_local_user_view_from_jwt;
 use lemmy_db_schema::source::local_site::LocalSite;
 use lemmy_utils::{claims::Claims, rate_limit::RateLimit, REQWEST_TIMEOUT};
 use lemmy_websocket::LemmyContext;
@@ -126,10 +126,9 @@ async fn full_res(
   context: web::Data<LemmyContext>,
 ) -> Result<HttpResponse, Error> {
   // block access to images if instance is private and unauthorized, public
-  let local_site = blocking(context.pool(), LocalSite::read)
-    .await?
+  let local_site = LocalSite::read(context.pool())
+    .await
     .map_err(error::ErrorBadRequest)?;
-  // The site might not be set up yet
   if local_site.private_instance {
     let jwt = req
       .cookie("jwt")
diff --git a/crates/routes/src/nodeinfo.rs b/crates/routes/src/nodeinfo.rs
index c0d7cf7e..d5baf3aa 100644
--- a/crates/routes/src/nodeinfo.rs
+++ b/crates/routes/src/nodeinfo.rs
@@ -1,6 +1,5 @@
 use actix_web::{error::ErrorBadRequest, *};
 use anyhow::anyhow;
-use lemmy_api_common::utils::blocking;
 use lemmy_db_views::structs::SiteView;
 use lemmy_utils::{error::LemmyError, version};
 use lemmy_websocket::LemmyContext;
@@ -29,8 +28,8 @@ async fn node_info_well_known(
 }
 
 async fn node_info(context: web::Data<LemmyContext>) -> Result<HttpResponse, Error> {
-  let site_view = blocking(context.pool(), SiteView::read_local)
-    .await?
+  let site_view = SiteView::read_local(context.pool())
+    .await
     .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))?;
 
   let protocols = if site_view.local_site.federation_enabled {
diff --git a/crates/routes/src/webfinger.rs b/crates/routes/src/webfinger.rs
index a13aad3e..33322347 100644
--- a/crates/routes/src/webfinger.rs
+++ b/crates/routes/src/webfinger.rs
@@ -1,6 +1,5 @@
 use actix_web::{web, web::Query, HttpResponse};
 use anyhow::Context;
-use lemmy_api_common::utils::blocking;
 use lemmy_apub::fetcher::webfinger::{WebfingerLink, WebfingerResponse};
 use lemmy_db_schema::{
   source::{community::Community, person::Person},
@@ -43,18 +42,14 @@ async fn get_webfinger_response(
     .to_string();
 
   let name_ = name.clone();
-  let user_id: Option<Url> = blocking(context.pool(), move |conn| {
-    Person::read_from_name(conn, &name_, false)
-  })
-  .await?
-  .ok()
-  .map(|c| c.actor_id.into());
-  let community_id: Option<Url> = blocking(context.pool(), move |conn| {
-    Community::read_from_name(conn, &name, false)
-  })
-  .await?
-  .ok()
-  .map(|c| c.actor_id.into());
+  let user_id: Option<Url> = Person::read_from_name(context.pool(), &name_, false)
+    .await
+    .ok()
+    .map(|c| c.actor_id.into());
+  let community_id: Option<Url> = Community::read_from_name(context.pool(), &name, false)
+    .await
+    .ok()
+    .map(|c| c.actor_id.into());
 
   // Mastodon seems to prioritize the last webfinger item in case of duplicates. Put
   // community last so that it gets prioritized. For Lemmy the order doesnt matter.
diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml
index 6e0fbcbd..f4537590 100644
--- a/crates/utils/Cargo.toml
+++ b/crates/utils/Cargo.toml
@@ -17,30 +17,30 @@ doctest = false
 regex = "1.6.0"
 chrono = { version = "0.4.22", features = ["serde", "clock"], default-features = false }
 lettre = "0.10.1"
-tracing = "0.1.36"
+tracing = "0.1.37"
 tracing-error = "0.2.0"
 itertools = "0.10.5"
 rand = "0.8.5"
-serde = { version = "1.0.145", features = ["derive"] }
-serde_json = { version = "1.0.85", features = ["preserve_order"] }
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = { version = "1.0.87", features = ["preserve_order"] }
 comrak = { version = "0.14.0", default-features = false }
 once_cell = "1.15.0"
-openssl = "0.10.41"
+openssl = "0.10.42"
 url = { version = "2.3.1", features = ["serde"] }
 actix-web = { version = "4.2.1", default-features = false, features = ["rustls"] }
-anyhow = "1.0.65"
+anyhow = "1.0.66"
 reqwest-middleware = "0.1.6"
 strum = "0.24.1"
 strum_macros = "0.24.3"
-futures = "0.3.24"
-diesel = { version = "2.0.0", features = ["chrono"] }
+futures = "0.3.25"
+diesel = { version = "2.0.2", features = ["chrono"] }
 http = "0.2.8"
 deser-hjson = "1.0.2"
 smart-default = "0.6.0"
 jsonwebtoken = "8.1.1"
 doku = { version = "0.12.0", features = ["url-2"] }
-uuid = { version = "1.1.2", features = ["serde", "v4"] }
-html2text = "0.4.2"
+uuid = { version = "1.2.1", features = ["serde", "v4"] }
+html2text = "0.4.3"
 rosetta-i18n = "0.1.2"
 parking_lot = "0.12.1"
 typed-builder = "0.10.0"
diff --git a/crates/websocket/Cargo.toml b/crates/websocket/Cargo.toml
index dba9b106..c2d1618f 100644
--- a/crates/websocket/Cargo.toml
+++ b/crates/websocket/Cargo.toml
@@ -22,17 +22,17 @@ lemmy_db_views_actor = { version = "=0.16.5", path = "../db_views_actor", featur
 reqwest-middleware = "0.1.6"
 tracing = "0.1.36"
 rand = "0.8.5"
-serde = { version = "1.0.145", features = ["derive"] }
-serde_json = { version = "1.0.85", features = ["preserve_order"] }
+serde = { version = "1.0.147", features = ["derive"] }
+serde_json = { version = "1.0.87", features = ["preserve_order"] }
 actix = "0.13.0"
-anyhow = "1.0.65"
-diesel = "2.0.0"
-background-jobs = "0.12.0"
-tokio = "1.21.1"
+anyhow = "1.0.66"
+diesel = "2.0.2"
+background-jobs = "0.13.0"
+tokio = "1.21.2"
 strum = "0.24.1"
 strum_macros = "0.24.3"
 chrono = { version = "0.4.22", features = ["serde"], default-features = false }
 actix-web = { version = "4.2.1", default-features = false, features = ["rustls"] }
 actix-web-actors = { version = "4.1.0", default-features = false }
-opentelemetry = "0.17.0"
-tracing-opentelemetry = "0.17.2"
+opentelemetry = "0.18.0"
+tracing-opentelemetry = "0.18.0"
diff --git a/crates/websocket/src/chat_server.rs b/crates/websocket/src/chat_server.rs
index b0dcabc9..65ab4cbd 100644
--- a/crates/websocket/src/chat_server.rs
+++ b/crates/websocket/src/chat_server.rs
@@ -8,14 +8,11 @@ use crate::{
 };
 use actix::prelude::*;
 use anyhow::Context as acontext;
-use diesel::{
-  r2d2::{ConnectionManager, Pool},
-  PgConnection,
-};
 use lemmy_api_common::{comment::*, post::*};
 use lemmy_db_schema::{
   newtypes::{CommunityId, LocalUserId, PostId},
   source::secret::Secret,
+  utils::DbPool,
 };
 use lemmy_utils::{
   error::LemmyError,
@@ -71,7 +68,7 @@ pub struct ChatServer {
   pub(super) rng: ThreadRng,
 
   /// The DB Pool
-  pub(super) pool: Pool<ConnectionManager<PgConnection>>,
+  pub(super) pool: DbPool,
 
   /// The Settings
   pub(super) settings: Settings,
@@ -103,7 +100,7 @@ pub struct SessionInfo {
 impl ChatServer {
   #![allow(clippy::too_many_arguments)]
   pub fn startup(
-    pool: Pool<ConnectionManager<PgConnection>>,
+    pool: DbPool,
     rate_limiter: RateLimit,
     message_handler: MessageHandlerType,
     message_handler_crud: MessageHandlerCrudType,
diff --git a/crates/websocket/src/send.rs b/crates/websocket/src/send.rs
index 59187d2c..2793534f 100644
--- a/crates/websocket/src/send.rs
+++ b/crates/websocket/src/send.rs
@@ -8,7 +8,7 @@ use lemmy_api_common::{
   community::CommunityResponse,
   post::PostResponse,
   private_message::PrivateMessageResponse,
-  utils::{blocking, check_person_block, get_interface_language, send_email_to_user},
+  utils::{check_person_block, get_interface_language, send_email_to_user},
 };
 use lemmy_db_schema::{
   newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
@@ -34,10 +34,7 @@ pub async fn send_post_ws_message<OP: ToString + Send + OperationType + 'static>
   person_id: Option<PersonId>,
   context: &LemmyContext,
 ) -> Result<PostResponse, LemmyError> {
-  let post_view = blocking(context.pool(), move |conn| {
-    PostView::read(conn, post_id, person_id)
-  })
-  .await??;
+  let post_view = PostView::read(context.pool(), post_id, person_id).await?;
 
   let res = PostResponse { post_view };
 
@@ -71,10 +68,7 @@ pub async fn send_comment_ws_message<OP: ToString + Send + OperationType + 'stat
   recipient_ids: Vec<LocalUserId>,
   context: &LemmyContext,
 ) -> Result<CommentResponse, LemmyError> {
-  let mut view = blocking(context.pool(), move |conn| {
-    CommentView::read(conn, comment_id, person_id)
-  })
-  .await??;
+  let mut view = CommentView::read(context.pool(), comment_id, person_id).await?;
 
   if view.comment.deleted || view.comment.removed {
     view.comment = view.comment.blank_out_deleted_or_removed_info();
@@ -108,10 +102,7 @@ pub async fn send_community_ws_message<OP: ToString + Send + OperationType + 'st
   person_id: Option<PersonId>,
   context: &LemmyContext,
 ) -> Result<CommunityResponse, LemmyError> {
-  let community_view = blocking(context.pool(), move |conn| {
-    CommunityView::read(conn, community_id, person_id)
-  })
-  .await??;
+  let community_view = CommunityView::read(context.pool(), community_id, person_id).await?;
 
   let res = CommunityResponse { community_view };
 
@@ -136,10 +127,7 @@ pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
   websocket_id: Option<ConnectionId>,
   context: &LemmyContext,
 ) -> Result<PrivateMessageResponse, LemmyError> {
-  let mut view = blocking(context.pool(), move |conn| {
-    PrivateMessageView::read(conn, private_message_id)
-  })
-  .await??;
+  let mut view = PrivateMessageView::read(context.pool(), private_message_id).await?;
 
   // Blank out deleted or removed info
   if view.private_message.deleted {
@@ -153,10 +141,7 @@ pub async fn send_pm_ws_message<OP: ToString + Send + OperationType + 'static>(
   // Send notifications to the local recipient, if one exists
   if res.private_message_view.recipient.local {
     let recipient_id = res.private_message_view.recipient.id;
-    let local_recipient = blocking(context.pool(), move |conn| {
-      LocalUserView::read_person(conn, recipient_id)
-    })
-    .await??;
+    let local_recipient = LocalUserView::read_person(context.pool(), recipient_id).await?;
     context.chat_server().do_send(SendUserRoomMessage {
       op,
       response: res.clone(),
@@ -187,10 +172,7 @@ pub async fn send_local_notifs(
     .collect::<Vec<&MentionData>>()
   {
     let mention_name = mention.name.clone();
-    let user_view = blocking(context.pool(), move |conn| {
-      LocalUserView::read_from_name(conn, &mention_name)
-    })
-    .await?;
+    let user_view = LocalUserView::read_from_name(context.pool(), &mention_name).await;
     if let Ok(mention_user_view) = user_view {
       // TODO
       // At some point, make it so you can't tag the parent creator either
@@ -205,11 +187,9 @@ pub async fn send_local_notifs(
 
       // Allow this to fail softly, since comment edits might re-update or replace it
       // Let the uniqueness handle this fail
-      blocking(context.pool(), move |conn| {
-        PersonMention::create(conn, &user_mention_form)
-      })
-      .await?
-      .ok();
+      PersonMention::create(context.pool(), &user_mention_form)
+        .await
+        .ok();
 
       // Send an email to those local users that have notifications on
       if do_send_email {
@@ -226,10 +206,7 @@ pub async fn send_local_notifs(
 
   // Send comment_reply to the parent commenter / poster
   if let Some(parent_comment_id) = comment.parent_comment_id() {
-    let parent_comment = blocking(context.pool(), move |conn| {
-      Comment::read(conn, parent_comment_id)
-    })
-    .await??;
+    let parent_comment = Comment::read(context.pool(), parent_comment_id).await?;
 
     // Get the parent commenter local_user
     let parent_creator_id = parent_comment.creator_id;
@@ -241,10 +218,7 @@ pub async fn send_local_notifs(
 
     // Don't send a notif to yourself
     if parent_comment.creator_id != person.id && !creator_blocked {
-      let user_view = blocking(context.pool(), move |conn| {
-        LocalUserView::read_person(conn, parent_creator_id)
-      })
-      .await?;
+      let user_view = LocalUserView::read_person(context.pool(), parent_creator_id).await;
       if let Ok(parent_user_view) = user_view {
         recipient_ids.push(parent_user_view.local_user.id);
 
@@ -256,11 +230,9 @@ pub async fn send_local_notifs(
 
         // Allow this to fail softly, since comment edits might re-update or replace it
         // Let the uniqueness handle this fail
-        blocking(context.pool(), move |conn| {
-          CommentReply::create(conn, &comment_reply_form)
-        })
-        .await?
-        .ok();
+        CommentReply::create(context.pool(), &comment_reply_form)
+          .await
+          .ok();
 
         if do_send_email {
           let lang = get_interface_language(&parent_user_view);
@@ -282,10 +254,7 @@ pub async fn send_local_notifs(
 
     if post.creator_id != person.id && !creator_blocked {
       let creator_id = post.creator_id;
-      let parent_user = blocking(context.pool(), move |conn| {
-        LocalUserView::read_person(conn, creator_id)
-      })
-      .await?;
+      let parent_user = LocalUserView::read_person(context.pool(), creator_id).await;
       if let Ok(parent_user_view) = parent_user {
         recipient_ids.push(parent_user_view.local_user.id);
 
@@ -297,11 +266,9 @@ pub async fn send_local_notifs(
 
         // Allow this to fail softly, since comment edits might re-update or replace it
         // Let the uniqueness handle this fail
-        blocking(context.pool(), move |conn| {
-          CommentReply::create(conn, &comment_reply_form)
-        })
-        .await?
-        .ok();
+        CommentReply::create(context.pool(), &comment_reply_form)
+          .await
+          .ok();
 
         if do_send_email {
           let lang = get_interface_language(&parent_user_view);
diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile
index 14096dc0..b004720e 100644
--- a/docker/dev/Dockerfile
+++ b/docker/dev/Dockerfile
@@ -1,4 +1,4 @@
-ARG RUST_BUILDER_IMAGE=clux/muslrust:1.59.0
+ARG RUST_BUILDER_IMAGE=clux/muslrust:1.64.0
 
 FROM $RUST_BUILDER_IMAGE as chef
 USER root
diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml
index 52f987b2..c7f3e1ab 100644
--- a/docker/dev/docker-compose.yml
+++ b/docker/dev/docker-compose.yml
@@ -46,13 +46,13 @@ services:
       - pictrs
 
   lemmy-ui:
-    image: dessalines/lemmy-ui:dev
+    # image: dessalines/lemmy-ui:dev
     # use this to build your local lemmy ui image for development
     # run docker compose up --build
     # assuming lemmy-ui is cloned besides lemmy directory
-    # build: 
-    #  context: ../../../lemmy-ui
-    #  dockerfile: Dockerfile  
+    build: 
+     context: ../../../lemmy-ui
+     dockerfile: dev.dockerfile
     networks:
       - lemmyinternal
     environment:
diff --git a/docker/dev/lemmy.hjson b/docker/dev/lemmy.hjson
index 2bd0675a..cac95ffd 100644
--- a/docker/dev/lemmy.hjson
+++ b/docker/dev/lemmy.hjson
@@ -14,10 +14,6 @@
     host: postgres
   }
 
-  database: {
-    host: "postgres"
-  }
-
   hostname: "localhost"
   bind: "0.0.0.0"
   port: 8536
diff --git a/docker/federation/lemmy_alpha.hjson b/docker/federation/lemmy_alpha.hjson
index 9622ead4..5620c447 100644
--- a/docker/federation/lemmy_alpha.hjson
+++ b/docker/federation/lemmy_alpha.hjson
@@ -7,11 +7,12 @@
     admin_password: lemmylemmy
     site_name: lemmy-alpha
   }
+  # These are ignored, use LEMMY_DATABASE_URL
   database: {
-    database: lemmy
+    database: lemmy_alpha
     user: lemmy
     password: password
-    host: postgres_alpha
+    host: localhost
     port: 5432
     pool_size: 5
   }
diff --git a/docker/federation/lemmy_beta.hjson b/docker/federation/lemmy_beta.hjson
index f199055d..4aed8552 100644
--- a/docker/federation/lemmy_beta.hjson
+++ b/docker/federation/lemmy_beta.hjson
@@ -8,10 +8,10 @@
     site_name: lemmy-beta
   }
   database: {
-    database: lemmy
+    database: lemmy_beta
     user: lemmy
     password: password
-    host: postgres_beta
+    host: localhost
     port: 5432
     pool_size: 5
   }
diff --git a/docker/federation/lemmy_delta.hjson b/docker/federation/lemmy_delta.hjson
index 98f7606f..e2ed2547 100644
--- a/docker/federation/lemmy_delta.hjson
+++ b/docker/federation/lemmy_delta.hjson
@@ -8,10 +8,10 @@
     site_name: lemmy-delta
   }
   database: {
-    database: lemmy
+    database: lemmy_delta
     user: lemmy
     password: password
-    host: postgres_delta
+    host: localhost
     port: 5432
     pool_size: 5
   }
diff --git a/docker/federation/lemmy_epsilon.hjson b/docker/federation/lemmy_epsilon.hjson
index f7c64e2f..cdba0577 100644
--- a/docker/federation/lemmy_epsilon.hjson
+++ b/docker/federation/lemmy_epsilon.hjson
@@ -8,10 +8,10 @@
     site_name: lemmy-epsilon
   }
   database: {
-    database: lemmy
+    database: lemmy_epsilon
     user: lemmy
     password: password
-    host: postgres_epsilon
+    host: localhost
     port: 5432
     pool_size: 5
   }
diff --git a/docker/federation/lemmy_gamma.hjson b/docker/federation/lemmy_gamma.hjson
index 632f10df..80c75b25 100644
--- a/docker/federation/lemmy_gamma.hjson
+++ b/docker/federation/lemmy_gamma.hjson
@@ -8,10 +8,10 @@
     site_name: lemmy-gamma
   }
   database: {
-    database: lemmy
+    database: lemmy_gamma
     user: lemmy
     password: password
-    host: postgres_gamma
+    host: localhost
     port: 5432
     pool_size: 5
   }
diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile
index 33a77af8..eb6bc215 100644
--- a/docker/prod/Dockerfile
+++ b/docker/prod/Dockerfile
@@ -1,5 +1,5 @@
 # Build the project
-FROM clux/muslrust:1.59.0 as builder
+FROM clux/muslrust:1.64.0 as builder
 
 ARG CARGO_BUILD_TARGET=x86_64-unknown-linux-musl
 ARG RUSTRELEASEDIR="release"
diff --git a/docker/prod/Dockerfile.arm b/docker/prod/Dockerfile.arm
index 926fa8a7..62439468 100644
--- a/docker/prod/Dockerfile.arm
+++ b/docker/prod/Dockerfile.arm
@@ -1,4 +1,4 @@
-ARG RUST_BUILDER_IMAGE=rust:1.60-slim-buster
+ARG RUST_BUILDER_IMAGE=rust:1.64-slim-buster
 
 # Build Lemmy
 FROM $RUST_BUILDER_IMAGE as builder
diff --git a/src/code_migrations.rs b/src/code_migrations.rs
index 159514a6..4f8b2afa 100644
--- a/src/code_migrations.rs
+++ b/src/code_migrations.rs
@@ -2,8 +2,12 @@
 use activitypub_federation::core::signatures::generate_actor_keypair;
 use diesel::{
   sql_types::{Nullable, Text},
-  *,
+  ExpressionMethods,
+  IntoSql,
+  QueryDsl,
+  TextExpressionMethods,
 };
+use diesel_async::RunQueryDsl;
 use lemmy_api_common::lemmy_db_views::structs::SiteView;
 use lemmy_apub::{
   generate_followers_url,
@@ -27,36 +31,34 @@ use lemmy_db_schema::{
     site::{Site, SiteInsertForm, SiteUpdateForm},
   },
   traits::Crud,
-  utils::naive_now,
+  utils::{get_conn, naive_now, DbPool},
 };
 use lemmy_utils::{error::LemmyError, settings::structs::Settings};
 use tracing::info;
 use url::Url;
 
-pub fn run_advanced_migrations(
-  conn: &mut PgConnection,
-  settings: &Settings,
-) -> Result<(), LemmyError> {
+pub async fn run_advanced_migrations(pool: &DbPool, settings: &Settings) -> Result<(), LemmyError> {
   let protocol_and_hostname = &settings.get_protocol_and_hostname();
-  user_updates_2020_04_02(conn, protocol_and_hostname)?;
-  community_updates_2020_04_02(conn, protocol_and_hostname)?;
-  post_updates_2020_04_03(conn, protocol_and_hostname)?;
-  comment_updates_2020_04_03(conn, protocol_and_hostname)?;
-  private_message_updates_2020_05_05(conn, protocol_and_hostname)?;
-  post_thumbnail_url_updates_2020_07_27(conn, protocol_and_hostname)?;
-  apub_columns_2021_02_02(conn)?;
-  instance_actor_2022_01_28(conn, protocol_and_hostname)?;
-  regenerate_public_keys_2022_07_05(conn)?;
-  initialize_local_site_2022_10_10(conn, settings)?;
+  user_updates_2020_04_02(pool, protocol_and_hostname).await?;
+  community_updates_2020_04_02(pool, protocol_and_hostname).await?;
+  post_updates_2020_04_03(pool, protocol_and_hostname).await?;
+  comment_updates_2020_04_03(pool, protocol_and_hostname).await?;
+  private_message_updates_2020_05_05(pool, protocol_and_hostname).await?;
+  post_thumbnail_url_updates_2020_07_27(pool, protocol_and_hostname).await?;
+  apub_columns_2021_02_02(pool).await?;
+  instance_actor_2022_01_28(pool, protocol_and_hostname).await?;
+  regenerate_public_keys_2022_07_05(pool).await?;
+  initialize_local_site_2022_10_10(pool, settings).await?;
 
   Ok(())
 }
 
-fn user_updates_2020_04_02(
-  conn: &mut PgConnection,
+async fn user_updates_2020_04_02(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::person::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running user_updates_2020_04_02");
 
@@ -64,7 +66,8 @@ fn user_updates_2020_04_02(
   let incorrect_persons = person
     .filter(actor_id.like("http://changeme%"))
     .filter(local.eq(true))
-    .load::<Person>(conn)?;
+    .load::<Person>(conn)
+    .await?;
 
   for cperson in &incorrect_persons {
     let keypair = generate_actor_keypair()?;
@@ -80,7 +83,7 @@ fn user_updates_2020_04_02(
       .last_refreshed_at(Some(naive_now()))
       .build();
 
-    Person::update(conn, cperson.id, &form)?;
+    Person::update(pool, cperson.id, &form).await?;
   }
 
   info!("{} person rows updated.", incorrect_persons.len());
@@ -88,11 +91,12 @@ fn user_updates_2020_04_02(
   Ok(())
 }
 
-fn community_updates_2020_04_02(
-  conn: &mut PgConnection,
+async fn community_updates_2020_04_02(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::community::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running community_updates_2020_04_02");
 
@@ -100,7 +104,8 @@ fn community_updates_2020_04_02(
   let incorrect_communities = community
     .filter(actor_id.like("http://changeme%"))
     .filter(local.eq(true))
-    .load::<Community>(conn)?;
+    .load::<Community>(conn)
+    .await?;
 
   for ccommunity in &incorrect_communities {
     let keypair = generate_actor_keypair()?;
@@ -117,7 +122,7 @@ fn community_updates_2020_04_02(
       .last_refreshed_at(Some(naive_now()))
       .build();
 
-    Community::update(conn, ccommunity.id, &form)?;
+    Community::update(pool, ccommunity.id, &form).await?;
   }
 
   info!("{} community rows updated.", incorrect_communities.len());
@@ -125,11 +130,12 @@ fn community_updates_2020_04_02(
   Ok(())
 }
 
-fn post_updates_2020_04_03(
-  conn: &mut PgConnection,
+async fn post_updates_2020_04_03(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::post::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running post_updates_2020_04_03");
 
@@ -137,7 +143,8 @@ fn post_updates_2020_04_03(
   let incorrect_posts = post
     .filter(ap_id.like("http://changeme%"))
     .filter(local.eq(true))
-    .load::<Post>(conn)?;
+    .load::<Post>(conn)
+    .await?;
 
   for cpost in &incorrect_posts {
     let apub_id = generate_local_apub_endpoint(
@@ -146,10 +153,11 @@ fn post_updates_2020_04_03(
       protocol_and_hostname,
     )?;
     Post::update(
-      conn,
+      pool,
       cpost.id,
       &PostUpdateForm::builder().ap_id(Some(apub_id)).build(),
-    )?;
+    )
+    .await?;
   }
 
   info!("{} post rows updated.", incorrect_posts.len());
@@ -157,11 +165,12 @@ fn post_updates_2020_04_03(
   Ok(())
 }
 
-fn comment_updates_2020_04_03(
-  conn: &mut PgConnection,
+async fn comment_updates_2020_04_03(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::comment::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running comment_updates_2020_04_03");
 
@@ -169,7 +178,8 @@ fn comment_updates_2020_04_03(
   let incorrect_comments = comment
     .filter(ap_id.like("http://changeme%"))
     .filter(local.eq(true))
-    .load::<Comment>(conn)?;
+    .load::<Comment>(conn)
+    .await?;
 
   for ccomment in &incorrect_comments {
     let apub_id = generate_local_apub_endpoint(
@@ -178,10 +188,11 @@ fn comment_updates_2020_04_03(
       protocol_and_hostname,
     )?;
     Comment::update(
-      conn,
+      pool,
       ccomment.id,
       &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(),
-    )?;
+    )
+    .await?;
   }
 
   info!("{} comment rows updated.", incorrect_comments.len());
@@ -189,11 +200,12 @@ fn comment_updates_2020_04_03(
   Ok(())
 }
 
-fn private_message_updates_2020_05_05(
-  conn: &mut PgConnection,
+async fn private_message_updates_2020_05_05(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::private_message::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running private_message_updates_2020_05_05");
 
@@ -201,7 +213,8 @@ fn private_message_updates_2020_05_05(
   let incorrect_pms = private_message
     .filter(ap_id.like("http://changeme%"))
     .filter(local.eq(true))
-    .load::<PrivateMessage>(conn)?;
+    .load::<PrivateMessage>(conn)
+    .await?;
 
   for cpm in &incorrect_pms {
     let apub_id = generate_local_apub_endpoint(
@@ -210,12 +223,13 @@ fn private_message_updates_2020_05_05(
       protocol_and_hostname,
     )?;
     PrivateMessage::update(
-      conn,
+      pool,
       cpm.id,
       &PrivateMessageUpdateForm::builder()
         .ap_id(Some(apub_id))
         .build(),
-    )?;
+    )
+    .await?;
   }
 
   info!("{} private message rows updated.", incorrect_pms.len());
@@ -223,11 +237,12 @@ fn private_message_updates_2020_05_05(
   Ok(())
 }
 
-fn post_thumbnail_url_updates_2020_07_27(
-  conn: &mut PgConnection,
+async fn post_thumbnail_url_updates_2020_07_27(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   use lemmy_db_schema::schema::post::dsl::*;
+  let conn = &mut get_conn(pool).await?;
 
   info!("Running post_thumbnail_url_updates_2020_07_27");
 
@@ -244,7 +259,8 @@ fn post_thumbnail_url_updates_2020_07_27(
           .concat(thumbnail_url),
       ),
     )
-    .get_results::<Post>(conn)?;
+    .get_results::<Post>(conn)
+    .await?;
 
   info!("{} Post thumbnail_url rows updated.", res.len());
 
@@ -253,13 +269,15 @@ fn post_thumbnail_url_updates_2020_07_27(
 
 /// We are setting inbox and follower URLs for local and remote actors alike, because for now
 /// all federated instances are also Lemmy and use the same URL scheme.
-fn apub_columns_2021_02_02(conn: &mut PgConnection) -> Result<(), LemmyError> {
+async fn apub_columns_2021_02_02(pool: &DbPool) -> Result<(), LemmyError> {
+  let conn = &mut get_conn(pool).await?;
   info!("Running apub_columns_2021_02_02");
   {
     use lemmy_db_schema::schema::person::dsl::*;
     let persons = person
       .filter(inbox_url.like("http://changeme%"))
-      .load::<Person>(conn)?;
+      .load::<Person>(conn)
+      .await?;
 
     for p in &persons {
       let inbox_url_ = generate_inbox_url(&p.actor_id)?;
@@ -269,7 +287,8 @@ fn apub_columns_2021_02_02(conn: &mut PgConnection) -> Result<(), LemmyError> {
           inbox_url.eq(inbox_url_),
           shared_inbox_url.eq(shared_inbox_url_),
         ))
-        .get_result::<Person>(conn)?;
+        .get_result::<Person>(conn)
+        .await?;
     }
   }
 
@@ -277,7 +296,8 @@ fn apub_columns_2021_02_02(conn: &mut PgConnection) -> Result<(), LemmyError> {
     use lemmy_db_schema::schema::community::dsl::*;
     let communities = community
       .filter(inbox_url.like("http://changeme%"))
-      .load::<Community>(conn)?;
+      .load::<Community>(conn)
+      .await?;
 
     for c in &communities {
       let followers_url_ = generate_followers_url(&c.actor_id)?;
@@ -289,7 +309,8 @@ fn apub_columns_2021_02_02(conn: &mut PgConnection) -> Result<(), LemmyError> {
           inbox_url.eq(inbox_url_),
           shared_inbox_url.eq(shared_inbox_url_),
         ))
-        .get_result::<Community>(conn)?;
+        .get_result::<Community>(conn)
+        .await?;
     }
   }
 
@@ -300,12 +321,12 @@ fn apub_columns_2021_02_02(conn: &mut PgConnection) -> Result<(), LemmyError> {
 /// means we need to add actor columns to the site table, and initialize them with correct values.
 /// Before this point, there is only a single value in the site table which refers to the local
 /// Lemmy instance, so thats all we need to update.
-fn instance_actor_2022_01_28(
-  conn: &mut PgConnection,
+async fn instance_actor_2022_01_28(
+  pool: &DbPool,
   protocol_and_hostname: &str,
 ) -> Result<(), LemmyError> {
   info!("Running instance_actor_2021_09_29");
-  if let Ok(site_view) = SiteView::read_local(conn) {
+  if let Ok(site_view) = SiteView::read_local(pool).await {
     let site = site_view.site;
     // if site already has public key, we dont need to do anything here
     if !site.public_key.is_empty() {
@@ -320,7 +341,7 @@ fn instance_actor_2022_01_28(
       .private_key(Some(Some(key_pair.private_key)))
       .public_key(Some(key_pair.public_key))
       .build();
-    Site::update(conn, site.id, &site_form)?;
+    Site::update(pool, site.id, &site_form).await?;
   }
   Ok(())
 }
@@ -330,7 +351,8 @@ fn instance_actor_2022_01_28(
 /// key field is empty, generate a new keypair. It would be possible to regenerate only the pubkey,
 /// but thats more complicated and has no benefit, as federation is already broken for these actors.
 /// https://github.com/LemmyNet/lemmy/issues/2347
-fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), LemmyError> {
+async fn regenerate_public_keys_2022_07_05(pool: &DbPool) -> Result<(), LemmyError> {
+  let conn = &mut get_conn(pool).await?;
   info!("Running regenerate_public_keys_2022_07_05");
 
   {
@@ -339,7 +361,8 @@ fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), Lemm
     let communities: Vec<Community> = community
       .filter(local.eq(true))
       .filter(public_key.eq(""))
-      .load::<Community>(conn)?;
+      .load::<Community>(conn)
+      .await?;
     for community_ in communities {
       info!(
         "local community {} has empty public key field, regenerating key",
@@ -350,7 +373,7 @@ fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), Lemm
         .public_key(Some(key_pair.public_key))
         .private_key(Some(Some(key_pair.private_key)))
         .build();
-      Community::update(conn, community_.id, &form)?;
+      Community::update(pool, community_.id, &form).await?;
     }
   }
 
@@ -360,7 +383,8 @@ fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), Lemm
     let persons = person
       .filter(local.eq(true))
       .filter(public_key.eq(""))
-      .load::<Person>(conn)?;
+      .load::<Person>(conn)
+      .await?;
     for person_ in persons {
       info!(
         "local user {} has empty public key field, regenerating key",
@@ -371,7 +395,7 @@ fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), Lemm
         .public_key(Some(key_pair.public_key))
         .private_key(Some(Some(key_pair.private_key)))
         .build();
-      Person::update(conn, person_.id, &form)?;
+      Person::update(pool, person_.id, &form).await?;
     }
   }
   Ok(())
@@ -381,14 +405,14 @@ fn regenerate_public_keys_2022_07_05(conn: &mut PgConnection) -> Result<(), Lemm
 ///
 /// If a site already exists, the DB migration should generate a local_site row.
 /// This will only be run for brand new sites.
-fn initialize_local_site_2022_10_10(
-  conn: &mut PgConnection,
+async fn initialize_local_site_2022_10_10(
+  pool: &DbPool,
   settings: &Settings,
 ) -> Result<(), LemmyError> {
   info!("Running initialize_local_site_2022_10_10");
 
   // Check to see if local_site exists
-  if LocalSite::read(conn).is_ok() {
+  if LocalSite::read(pool).await.is_ok() {
     return Ok(());
   }
   info!("No Local Site found, creating it.");
@@ -398,7 +422,7 @@ fn initialize_local_site_2022_10_10(
     .expect("must have domain");
 
   // Upsert this to the instance table
-  let instance = Instance::create(conn, &domain)?;
+  let instance = Instance::create(pool, &domain).await?;
 
   if let Some(setup) = &settings.setup {
     let person_keypair = generate_actor_keypair()?;
@@ -419,14 +443,14 @@ fn initialize_local_site_2022_10_10(
       .inbox_url(Some(generate_inbox_url(&person_actor_id)?))
       .shared_inbox_url(Some(generate_shared_inbox_url(&person_actor_id)?))
       .build();
-    let person_inserted = Person::create(conn, &person_form)?;
+    let person_inserted = Person::create(pool, &person_form).await?;
 
     let local_user_form = LocalUserInsertForm::builder()
       .person_id(person_inserted.id)
       .password_encrypted(setup.admin_password.to_owned())
       .email(setup.admin_email.to_owned())
       .build();
-    LocalUser::create(conn, &local_user_form)?;
+    LocalUser::create(pool, &local_user_form).await?;
   };
 
   // Add an entry for the site table
@@ -448,14 +472,14 @@ fn initialize_local_site_2022_10_10(
     .private_key(Some(site_key_pair.private_key))
     .public_key(Some(site_key_pair.public_key))
     .build();
-  let site = Site::create(conn, &site_form)?;
+  let site = Site::create(pool, &site_form).await?;
 
   // Finally create the local_site row
   let local_site_form = LocalSiteInsertForm::builder()
     .site_id(site.id)
     .site_setup(Some(settings.setup.is_some()))
     .build();
-  let local_site = LocalSite::create(conn, &local_site_form)?;
+  let local_site = LocalSite::create(pool, &local_site_form).await?;
 
   // Create the rate limit table
   let local_site_rate_limit_form = LocalSiteRateLimitInsertForm::builder()
@@ -471,7 +495,7 @@ fn initialize_local_site_2022_10_10(
     .search(Some(999))
     .local_site_id(local_site.id)
     .build();
-  LocalSiteRateLimit::create(conn, &local_site_rate_limit_form)?;
+  LocalSiteRateLimit::create(pool, &local_site_rate_limit_form).await?;
 
   Ok(())
 }
diff --git a/src/main.rs b/src/main.rs
index 4667df44..fd0f3c70 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,13 +1,8 @@
 #[macro_use]
 extern crate diesel_migrations;
 
-use crate::diesel_migrations::MigrationHarness;
 use actix::prelude::*;
 use actix_web::{web::Data, *};
-use diesel::{
-  r2d2::{ConnectionManager, Pool},
-  PgConnection,
-};
 use diesel_migrations::EmbeddedMigrations;
 use doku::json::{AutoComments, Formatting};
 use lemmy_api::match_websocket_operation;
@@ -15,13 +10,15 @@ use lemmy_api_common::{
   lemmy_db_views::structs::SiteView,
   request::build_user_agent,
   utils::{
-    blocking,
     check_private_instance_and_federation_enabled,
     local_site_rate_limit_to_rate_limit_config,
   },
 };
 use lemmy_api_crud::match_websocket_operation_crud;
-use lemmy_db_schema::{source::secret::Secret, utils::get_database_url_from_env};
+use lemmy_db_schema::{
+  source::secret::Secret,
+  utils::{build_db_pool, get_database_url, run_migrations},
+};
 use lemmy_routes::{feeds, images, nodeinfo, webfinger};
 use lemmy_server::{
   api_routes,
@@ -69,40 +66,28 @@ async fn main() -> Result<(), LemmyError> {
 
   init_logging(&settings.opentelemetry_url)?;
 
-  // Set up the r2d2 connection pool
-  let db_url = match get_database_url_from_env() {
-    Ok(url) => url,
-    Err(_) => settings.get_database_url(),
-  };
-  let manager = ConnectionManager::<PgConnection>::new(&db_url);
-  let pool = Pool::builder()
-    .max_size(settings.database.pool_size)
-    .min_idle(Some(1))
-    .build(manager)?;
+  // Set up the bb8 connection pool
+  let db_url = get_database_url(Some(&settings));
+  run_migrations(&db_url);
 
   // Run the migrations from code
-  let settings_cloned = settings.to_owned();
-  blocking(&pool, move |conn| {
-    let _ = conn
-      .run_pending_migrations(MIGRATIONS)
-      .map_err(|_| LemmyError::from_message("Couldn't run migrations"))?;
-    run_advanced_migrations(conn, &settings_cloned)?;
-    Ok(()) as Result<(), LemmyError>
-  })
-  .await??;
+  let pool = build_db_pool(&settings).await?;
+  run_advanced_migrations(&pool, &settings).await?;
 
   // Schedules various cleanup tasks for the DB
-  let pool2 = pool.clone();
   thread::spawn(move || {
-    scheduled_tasks::setup(pool2).expect("Couldn't set up scheduled_tasks");
+    scheduled_tasks::setup(db_url).expect("Couldn't set up scheduled_tasks");
   });
 
   // Initialize the secrets
-  let conn = &mut pool.get()?;
-  let secret = Secret::init(conn).expect("Couldn't initialize secrets.");
+  let secret = Secret::init(&pool)
+    .await
+    .expect("Couldn't initialize secrets.");
 
   // Make sure the local site is set up.
-  let site_view = SiteView::read_local(conn).expect("local site not set up");
+  let site_view = SiteView::read_local(&pool)
+    .await
+    .expect("local site not set up");
   let local_site = site_view.local_site;
   let federation_enabled = local_site.federation_enabled;
 
diff --git a/src/scheduled_tasks.rs b/src/scheduled_tasks.rs
index 108de672..5173a317 100644
--- a/src/scheduled_tasks.rs
+++ b/src/scheduled_tasks.rs
@@ -1,17 +1,18 @@
-// Scheduler, and trait for .seconds(), .minutes(), etc.
 use clokwerk::{Scheduler, TimeUnits};
 // Import week days and WeekDay
 use diesel::{sql_query, PgConnection, RunQueryDsl};
-use lemmy_db_schema::{source::activity::Activity, utils::DbPool};
+use diesel::{Connection, ExpressionMethods, QueryDsl};
 use lemmy_utils::error::LemmyError;
 use std::{thread, time::Duration};
 use tracing::info;
 
 /// Schedules various cleanup tasks for lemmy in a background thread
-pub fn setup(pool: DbPool) -> Result<(), LemmyError> {
+pub fn setup(db_url: String) -> Result<(), LemmyError> {
+  // Setup the connections
   let mut scheduler = Scheduler::new();
 
-  let mut conn = pool.get()?;
+  let mut conn = PgConnection::establish(&db_url).expect("could not establish connection");
+
   active_counts(&mut conn);
   update_banned_when_expired(&mut conn);
 
@@ -19,13 +20,14 @@ pub fn setup(pool: DbPool) -> Result<(), LemmyError> {
   // TODO remove this for now, since it slows down startup a lot on lemmy.ml
   reindex_aggregates_tables(&mut conn, true);
   scheduler.every(1.hour()).run(move || {
-    active_counts(&mut conn);
-    update_banned_when_expired(&mut conn);
-    reindex_aggregates_tables(&mut conn, true);
-    drop_ccnew_indexes(&mut conn);
+    let conn = &mut PgConnection::establish(&db_url)
+      .unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
+    active_counts(conn);
+    update_banned_when_expired(conn);
+    reindex_aggregates_tables(conn, true);
+    drop_ccnew_indexes(conn);
   });
 
-  let mut conn = pool.get()?;
   clear_old_activities(&mut conn);
   scheduler.every(1.weeks()).run(move || {
     clear_old_activities(&mut conn);
@@ -61,8 +63,12 @@ fn reindex_table(conn: &mut PgConnection, table_name: &str, concurrently: bool)
 
 /// Clear old activities (this table gets very large)
 fn clear_old_activities(conn: &mut PgConnection) {
+  use diesel::dsl::*;
+  use lemmy_db_schema::schema::activity::dsl::*;
   info!("Clearing old activities...");
-  Activity::delete_olds(conn).expect("clear old activities");
+  diesel::delete(activity.filter(published.lt(now - 6.months())))
+    .execute(conn)
+    .expect("clear old activities");
   info!("Done.");
 }
 
-- 
2.44.1