diff --git a/src/metabase/async/api_response.clj b/src/metabase/async/api_response.clj
index 46b5fc9b5c97cde83ee7d631b9544f5fd3bdcc33..16f5730becfe4fd818a9b79123c268f86bf33985 100644
--- a/src/metabase/async/api_response.clj
+++ b/src/metabase/async/api_response.clj
@@ -186,12 +186,10 @@
     (log/debug (u/format-color 'green (trs "starting streaming response")))
     (write-chan-vals-to-writer! (async-keepalive-channel chan) (io/writer output-stream))))
 
+;; `defendpoint-async` responses
 (extend-protocol Sendable
   ManyToManyChannel
   (send* [input-chan _ respond _]
-    (respond (-> (response/response input-chan)
-                 (assoc :content-type "applicaton/json; charset=utf-8")
-                 ;; tell nginx not to batch streaming responses -- otherwise the keepalive bytes aren't written and
-                 ;; the entire purpose is defeated. See
-                 ;; https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache
-                 (assoc-in [:headers "X-Accel-Buffering"] "no")))))
+    (respond
+     (assoc (response/response input-chan)
+       :content-type "applicaton/json; charset=utf-8"))))
diff --git a/src/metabase/handler.clj b/src/metabase/handler.clj
index d82c3ded88dbc6ef07ff5f7ce4a31c57ae884438..bf0614c6717cb2bb99861707375863df726a80e5 100644
--- a/src/metabase/handler.clj
+++ b/src/metabase/handler.clj
@@ -40,5 +40,6 @@
    mw.misc/bind-user-locale                ; Binds *locale* for i18n
    wrap-cookies                            ; Parses cookies in the request map and assocs as :cookies
    mw.misc/add-content-type                ; Adds a Content-Type header for any response that doesn't already have one
+   mw.misc/disable-streaming-buffering     ; Add header to streaming (async) responses so ngnix doesn't buffer keepalive bytes
    mw.misc/wrap-gzip))                     ; GZIP response if client can handle it
 ;; ▲▲▲ PRE-PROCESSING ▲▲▲ happens from BOTTOM-TO-TOP
diff --git a/src/metabase/middleware/misc.clj b/src/metabase/middleware/misc.clj
index bee301fd081290ec58fe11846e76ce4ddd5b848e..7f8d8d862c44f8df170ff17b69e72dd527bbf758 100644
--- a/src/metabase/middleware/misc.clj
+++ b/src/metabase/middleware/misc.clj
@@ -8,7 +8,8 @@
             [metabase.util.i18n :refer [trs]]
             [puppetlabs.i18n.core :as puppet-i18n]
             [ring.middleware.gzip :as ring.gzip])
-  (:import [java.io File InputStream]))
+  (:import clojure.core.async.impl.channels.ManyToManyChannel
+           [java.io File InputStream]))
 
 (defn- add-content-type* [request response]
   (update-in
@@ -98,3 +99,21 @@
      request
      (comp respond (partial wrap-gzip* request))
      raise)))
+
+
+;;; ------------------------------------------ Disable Streaming Buffering -------------------------------------------
+
+(defn- maybe-add-disable-buffering-header [{:keys [body], :as response}]
+  (cond-> response
+    (instance? ManyToManyChannel body)
+    (assoc-in [:headers "X-Accel-Buffering"] "no")))
+
+(defn disable-streaming-buffering
+  "Tell nginx not to batch streaming responses -- otherwise the keepalive bytes aren't written and
+  the entire purpose is defeated. See https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cache"
+  [handler]
+  (fn [request respond raise]
+    (handler
+     request
+     (comp respond maybe-add-disable-buffering-header)
+     raise)))