diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp
index fd161977493ac97bb039d8bf94fe898b970e8d68..2cdd6cf06a5e6a43e02aaa2ff6f13617a73a875a 100644
--- a/src/common/logging/backend.cpp
+++ b/src/common/logging/backend.cpp
@@ -4,6 +4,7 @@
 #include <atomic>
 #include <chrono>
 #include <climits>
+#include <mutex>
 #include <thread>
 
 #include <fmt/format.h>
@@ -231,8 +232,15 @@ public:
         if (!filter.CheckMessage(log_class, log_level)) {
             return;
         }
-        message_queue.EmplaceWait(
-            CreateEntry(log_class, log_level, filename, line_num, function, std::move(message)));
+
+        auto entry =
+            CreateEntry(log_class, log_level, filename, line_num, function, std::move(message));
+        if (Settings::values.log_async) {
+            message_queue.EmplaceWait(entry);
+        } else {
+            std::scoped_lock l{sync_mutex};
+            ForEachBackend([&entry](Backend& backend) { backend.Write(entry); });
+        }
     }
 
 private:
@@ -313,6 +321,7 @@ private:
 #endif
 
     MPSCQueue<Entry> message_queue{};
+    std::mutex sync_mutex;
     std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
     std::jthread backend_thread;
 };
@@ -345,9 +354,11 @@ void SetColorConsoleBackendEnabled(bool enabled) {
 void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename,
                        unsigned int line_num, const char* function, fmt::string_view format,
                        const fmt::format_args& args) {
-    if (!initialization_in_progress_suppress_logging) {
-        Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
-                                   fmt::vformat(format, args));
+    if (initialization_in_progress_suppress_logging) {
+        return;
     }
+
+    Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function,
+                               fmt::vformat(format, args));
 }
 } // namespace Common::Log
diff --git a/src/common/logging/filter.cpp b/src/common/logging/filter.cpp
index 4e3a614a451bd8b51482828d0cf23cec98f1c459..c16f4df3aaf8fc9590f88e7a6f25309f855e6738 100644
--- a/src/common/logging/filter.cpp
+++ b/src/common/logging/filter.cpp
@@ -171,6 +171,7 @@ const char* GetLogClassName(Class log_class) {
 #define SUB(x, y)                                                                                  \
     case Class::x##_##y:                                                                           \
         return #x "." #y;
+//        return #x "_" #y;
         ALL_LOG_CLASSES()
 #undef CLS
 #undef SUB
diff --git a/src/common/settings.h b/src/common/settings.h
index 48f127bde8ba35f82413fcb3957cdfc2804697bb..829759c94b2493d5b3f88a6d59712cdb7b4acdcf 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -604,6 +604,7 @@ struct Values {
 
     // Miscellaneous
     Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
+    Setting<bool> log_async{linkage, true, "log_async", Category::Miscellaneous};
     Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
 
     // Network
diff --git a/src/suyu/configuration/configure_debug.cpp b/src/suyu/configuration/configure_debug.cpp
index b4fa4eca091a67ef1fa20ef437d0cbe70e838e9e..6f9bb36340dc28943cbc7d53f46d7ec799b30e57 100644
--- a/src/suyu/configuration/configure_debug.cpp
+++ b/src/suyu/configuration/configure_debug.cpp
@@ -73,6 +73,7 @@ void ConfigureDebug::SetConfiguration() {
     ui->disable_loop_safety_checks->setChecked(
         Settings::values.disable_shader_loop_safety_checks.GetValue());
     ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue());
+    ui->log_async->setChecked(Settings::values.log_async.GetValue());
     ui->perform_vulkan_check->setChecked(Settings::values.perform_vulkan_check.GetValue());
 
 #ifdef SUYU_USE_QT_WEB_ENGINE
@@ -115,6 +116,7 @@ void ConfigureDebug::ApplyConfiguration() {
     Common::Log::Filter filter;
     filter.ParseFilterString(Settings::values.log_filter.GetValue());
     Common::Log::SetGlobalFilter(filter);
+    Settings::values.log_async = ui->log_async->isChecked();
 }
 
 void ConfigureDebug::changeEvent(QEvent* event) {
diff --git a/src/suyu/configuration/configure_debug.ui b/src/suyu/configuration/configure_debug.ui
index ed48b2f8f6afacb0d43567787c997d4a67f59dfa..e5b76290e66d6ac09f4c3ca0de628bc7396a2d95 100644
--- a/src/suyu/configuration/configure_debug.ui
+++ b/src/suyu/configuration/configure_debug.ui
@@ -164,6 +164,20 @@
            </property>
           </widget>
          </item>
+         <item row="2" column="1">
+          <widget class="QCheckBox" name="log_async">
+           <property name="enabled">
+            <bool>true</bool>
+           </property>
+           <property name="toolTip">
+            <string>When checked, logging will run asynchronously. This may cut the log on crashes.
+When unchecked, logging will run synchronously. This will slow down the emulator, but allow all logs to be written. Useful for debugging.</string>
+           </property>
+           <property name="text">
+            <string>Log asynchronously</string>
+           </property>
+          </widget>
+         </item>
          <item row="0" column="0" colspan="2">
           <widget class="QWidget" name="logging_widget" native="true">
            <property name="sizePolicy">
@@ -199,7 +213,14 @@
              </widget>
             </item>
             <item>
-             <widget class="QLineEdit" name="log_filter_edit"/>
+             <widget class="QLineEdit" name="log_filter_edit">
+              <property name="toolTip">
+               <string>Log filter in the form <class>:<level>.
+Separate multiple filters with a space.
+Levels: Trace, Debug, Info, Warning, Error, Critical
+Classes: See Common/logging/types.h</string>
+              </property>
+             </widget>
             </item>
            </layout>
           </widget>