diff --git a/src/metabase/pulse/render.clj b/src/metabase/pulse/render.clj
index 59b8c2398633f88be709bca92c911c3df5a54af0..8ac314f25b28fab5b4d30549301c1c8ee7284bd8 100644
--- a/src/metabase/pulse/render.clj
+++ b/src/metabase/pulse/render.clj
@@ -411,11 +411,6 @@
 (defn- mb-hash-str [image-hash]
   (str image-hash "@metabase"))
 
-(defn- resource-path->content-id-pair [path]
-  (let [external-link-url (io/resource path)]
-    [(mb-hash-str (hash-image-url external-link-url))
-     external-link-url]))
-
 (defn- write-byte-array-to-temp-file
   [^bytes img-bytes]
   (let [f (doto (java.io.File/createTempFile "metabase_pulse_image_" ".png")
@@ -424,22 +419,72 @@
       (.write fos img-bytes))
     f))
 
-(defn- byte-array->content-id-pair
-  [^bytes img-bytes]
-  (let [f (write-byte-array-to-temp-file img-bytes)]
-    [(mb-hash-str (hash-bytes img-bytes))
-     (io/as-url f)]))
+(defn- byte-array->url [^bytes img-bytes]
+  (-> img-bytes write-byte-array-to-temp-file io/as-url))
+
+(defmulti ^:private make-image-bundle
+  "Create an image bundle. An image bundle contains the data needed to either encode the image inline (when
+  `RENDER-TYPE` is `:inline`), or create the hashes/references needed for an attached image (`RENDER-TYPE` of
+  `:attachment`)"
+  (fn [render-type url-or-bytes]
+    [render-type (class url-or-bytes)]))
+
+(defmethod make-image-bundle [:attachment java.net.URL]
+  [render-type ^java.net.URL url]
+  (let [content-id (mb-hash-str (hash-image-url url))]
+    {:content-id  content-id
+     :image-url   url
+     :image-src   (content-id-reference content-id)
+     :render-type render-type}))
+
+(defmethod make-image-bundle [:attachment (class (byte-array 0))]
+  [render-type image-bytes]
+  (let [image-url (byte-array->url image-bytes)
+        content-id (mb-hash-str (hash-bytes image-bytes))]
+    {:content-id  content-id
+     :image-url   image-url
+     :image-src   (content-id-reference content-id)
+     :render-type render-type}))
+
+(defmethod make-image-bundle [:inline java.net.URL]
+  [render-type ^java.net.URL url]
+  {:image-src   (-> url io/input-stream IOUtils/toByteArray render-img-data-uri)
+   :image-url   url
+   :render-type render-type})
+
+(defmethod make-image-bundle [:inline (class (byte-array 0))]
+  [render-type image-bytes]
+  {:image-src   (render-img-data-uri image-bytes)
+   :render-type render-type})
+
+(def ^:private external-link-url (io/resource "frontend_client/app/assets/img/external_link.png"))
+(def ^:private no-results-url    (io/resource "frontend_client/app/assets/img/pulse_no_results@2x.png"))
 
 (def ^:private external-link-image
   (delay
-   (resource-path->content-id-pair "frontend_client/app/assets/img/external_link.png")))
+   (make-image-bundle :attachment external-link-url)))
 
 (def ^:private no-results-image
   (delay
-   (resource-path->content-id-pair "frontend_client/app/assets/img/pulse_no_results@2x.png")))
+   (make-image-bundle :attachment no-results-url)))
+
+(defn- external-link-image-bundle [render-type]
+  (case render-type
+    :attachment @external-link-image
+    :inline (make-image-bundle render-type external-link-url)))
+
+(defn- no-results-image-bundle [render-type]
+  (case render-type
+    :attachment @no-results-image
+    :inline (make-image-bundle render-type no-results-url)))
+
+(defn- image-bundle->attachment [{:keys [render-type content-id image-url]}]
+  (case render-type
+    :attachment {content-id image-url}
+    :inline     nil))
 
 (s/defn ^:private render:sparkline :- RenderedPulseCard
-  [timezone card {:keys [rows cols]}]
+  [render-type timezone card {:keys [rows cols]}]
   (let [ft-row (if (datetime-field? (first cols))
                  #(.getTime ^Date (u/->Timestamp %))
                  identity)
@@ -462,14 +507,14 @@
         rows'  (reverse (take-last 2 rows))
         values (map (comp format-number second) rows')
         labels (format-timestamp-pair timezone (map first rows') (first cols))
-        [content-id png-url] (byte-array->content-id-pair (render-sparkline-to-png xs' ys' 524 130))]
+        image-bundle (make-image-bundle render-type (render-sparkline-to-png xs' ys' 524 130))]
 
-    {:attachments (when (and content-id png-url)
-                    {content-id png-url})
+    {:attachments (when image-bundle
+                    (image-bundle->attachment image-bundle))
      :content     [:div
                    [:img {:style (style {:display :block
                                          :width :100%})
-                          :src   (content-id-reference content-id)}]
+                          :src   (:image-src image-bundle)}]
                    [:table
                     [:tr
                      [:td {:style (style {:color         color-brand
@@ -492,13 +537,12 @@
                       (second labels)]]]]}))
 
 (s/defn ^:private render:empty :- RenderedPulseCard
-  [_ _]
-  (let [[content-id no-results-url] @no-results-image]
-    {:attachments (when (and content-id no-results-url)
-                    {content-id no-results-url})
+  [render-type _ _]
+  (let [image-bundle (no-results-image-bundle render-type)]
+    {:attachments (image-bundle->attachment image-bundle)
      :content     [:div {:style (style {:text-align :center})}
                    [:img {:style (style {:width :104px})
-                          :src   (content-id-reference content-id)}]
+                          :src   (:image-src image-bundle)}]
                    [:div {:style (style {:margin-top :8px
                                          :color      color-gray-4})}
                     "No results"]]}))
@@ -528,12 +572,12 @@
       :else                                                        :table)))
 
 (s/defn ^:private make-title-if-needed :- (s/maybe RenderedPulseCard)
-  [card]
+  [render-type card]
   (when *include-title*
-    (let [[content-id link-url] (when *include-buttons*
-                                  @external-link-image)]
-      {:attachments (when (and content-id link-url)
-                      {content-id link-url})
+    (let [image-bundle (when *include-buttons*
+                         (external-link-image-bundle render-type))]
+      {:attachments (when image-bundle
+                      (image-bundle->attachment image-bundle))
        :content     [:table {:style (style {:margin-bottom :8px
                                             :width         :100%})}
                      [:tbody
@@ -544,18 +588,18 @@
                         (when *include-buttons*
                           [:img {:style (style {:width :16px})
                                  :width 16
-                                 :src   (content-id-reference content-id)}])]]]]})))
+                                 :src   (:image-src image-bundle)}])]]]]})))
 
 (s/defn ^:private render-pulse-card-body :- RenderedPulseCard
-  [timezone card {:keys [data error]}]
+  [render-type timezone card {:keys [data error]}]
   (try
     (when error
       (let [^String msg (tru "Card has errors: {0}" error)]
         (throw (Exception. msg))))
     (case (detect-pulse-card-type card data)
-      :empty     (render:empty     card data)
+      :empty     (render:empty     render-type card data)
       :scalar    (render:scalar    timezone card data)
-      :sparkline (render:sparkline timezone card data)
+      :sparkline (render:sparkline render-type timezone card data)
       :bar       (render:bar       timezone card data)
       :table     (render:table     timezone card data)
       {:attachments nil
@@ -572,11 +616,11 @@
                                           :padding     :16px})}
                      "An error occurred while displaying this card."]})))
 
-(s/defn render-pulse-card :- RenderedPulseCard
+(s/defn ^:private render-pulse-card :- RenderedPulseCard
   "Render a single CARD for a `Pulse` to Hiccup HTML. RESULT is the QP results."
-  [timezone card results]
-  (let [{title :content title-attachments :attachments} (make-title-if-needed card)
-        {pulse-body :content body-attachments :attachments} (render-pulse-card-body timezone card results)]
+  [render-type timezone card results]
+  (let [{title :content title-attachments :attachments} (make-title-if-needed render-type card)
+        {pulse-body :content body-attachments :attachments} (render-pulse-card-body render-type timezone card results)]
     {:attachments (merge title-attachments body-attachments)
      :content     [:a {:href   (card-href card)
                        :target "_blank"
@@ -592,13 +636,13 @@
   "Same as `render-pulse-card` but isn't intended for an email, rather for previewing so there is no need for
   attachments"
   [timezone card results]
-  (:content (render-pulse-card timezone card results)))
+  (:content (render-pulse-card :inline timezone card results)))
 
 (s/defn render-pulse-section :- RenderedPulseCard
   "Render a specific section of a Pulse, i.e. a single Card, to Hiccup HTML."
   [timezone {:keys [card result]}]
   (let [{:keys [attachments content]} (binding [*include-title* true]
-                                        (render-pulse-card timezone card result))]
+                                        (render-pulse-card :attachment timezone card result))]
     {:attachments attachments
      :content     [:div {:style (style {:margin-top       :10px
                                         :margin-bottom    :20px
@@ -611,4 +655,4 @@
 (defn render-pulse-card-to-png
   "Render a PULSE-CARD as a PNG. DATA is the `:data` from a QP result (I think...)"
   ^bytes [timezone pulse-card result]
-  (render-html-to-png (render-pulse-card timezone pulse-card result) card-width))
+  (render-html-to-png (render-pulse-card :inline timezone pulse-card result) card-width))