<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Colin White</title>
    <description>The latest articles on Forem by Colin White (@maybecolin).</description>
    <link>https://forem.com/maybecolin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F60837%2F5f6124a0-328d-4acc-a554-e89ae05a6612.jpg</url>
      <title>Forem: Colin White</title>
      <link>https://forem.com/maybecolin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/maybecolin"/>
    <language>en</language>
    <item>
      <title>The developer's guide to Slack's Markdown formatting</title>
      <dc:creator>Colin White</dc:creator>
      <pubDate>Tue, 31 Oct 2023 18:06:17 +0000</pubDate>
      <link>https://forem.com/knocklabs/the-developers-guide-to-slacks-markdown-formatting-22cl</link>
      <guid>https://forem.com/knocklabs/the-developers-guide-to-slacks-markdown-formatting-22cl</guid>
      <description>&lt;p&gt;&lt;a href="https://api.slack.com/reference/surfaces/formatting"&gt;Slack mrkdwn&lt;/a&gt; is Slack’s version of the Markdown language tailored for their platform. It allows developers to craft visually appealing and structured messages as well as emphasize critical information and add flair to their Slack messages.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll explore the nuances of mrkdwn, from its basic formatting capabilities to advanced features, coupled with practical examples to get you started and build the right Slack notifications for your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  mrkdwn isn’t Markdown
&lt;/h2&gt;

&lt;p&gt;At first glance, Slack’s mrkdwn and the popular Markdown syntax appear remarkably similar.&lt;/p&gt;

&lt;p&gt;Both Slack’s mrkdwn and John Gruber’s Markdown syntax offer a way to richly format text using simple, plaintext notations. However, the design and capabilities of each of the languages is different due to their different purposes.&lt;/p&gt;

&lt;p&gt;Markdown was designed as a lightweight markup language to convert plaintext into structurally valid HTML. It allows writers to easily ‘markup’ their text to convert it cleanly into HTML. Most developers will be used to Markdown in Github. You can use Markdown in both the Readme of a repo and individual commit messages. Markdown is also a core component of the Notion platform.&lt;/p&gt;

&lt;p&gt;Slack’s mrkdwn is a custom formatting syntax tailored specifically for the Slack platform. Its sole goal is to make it easier to write rich, visually appealing text within Slack and take advantage of the core features of the platform such as @-mentions and channels.&lt;/p&gt;

&lt;p&gt;The different purpose leads to core differences in the syntax. Most obviously, Markdown supports multiple header levels using #. For instance, &lt;code&gt;### Header 3&lt;/code&gt; would represent a &lt;code&gt;&amp;lt;h3&amp;gt;&lt;/code&gt; tag in HTML. mrkdwn doesn’t support multiple header levels in the same way. When would you use a header in a Slack message? It’s more streamlined for shorter messages.&lt;/p&gt;

&lt;p&gt;The same goes for tables or syntax highlighting. These are core for a full document, but less important in Slack messages. Conversely, mrkdwn has special link formats, like &lt;code&gt;&amp;lt;@U12345678&amp;gt;&lt;/code&gt; for user mentions or &lt;code&gt;&amp;lt;!channel&amp;gt;&lt;/code&gt; to notify all members of a channel. Markdown doesn’t have a native equivalent for these functionalities given how platform-specific they are.&lt;/p&gt;

&lt;p&gt;There are also some design choices within mrkdwn that are different from Markdown, such as the use of underscores for italics rather than a single asterisk, or angle brackets for links instead of square brackets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic formatting: the foundations of mrkdwn
&lt;/h2&gt;

&lt;p&gt;The core elements of mrkdwn help you convey your messages with clarity, emphasize key points, and make your text easy to scan and understand.&lt;/p&gt;

&lt;p&gt;Three elements are commonly used with regular text:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrapping your text with asterisks (&lt;code&gt;*&lt;/code&gt;) characters bolds the text to emphasize a word or phrase.&lt;/li&gt;
&lt;li&gt;Wrapping your text with underscores (&lt;code&gt;_&lt;/code&gt;) characters italicizes the text to emphasize subtly or indicate titles of works.&lt;/li&gt;
&lt;li&gt;Wrapping your text with tildes (&lt;code&gt;~&lt;/code&gt;) characters strikes through the text to indicate corrections or highlight something that’s no longer relevant.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then we have two ways to add code to Slack messages. This could be particularly useful if you are building alerts for an application monitoring platform and need to show code that has failed.&lt;/p&gt;

&lt;p&gt;Inline code is good for highlighting code, commands, or special terminology. For this, you wrap your text with backticks (&lt;code&gt;`&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Multiline code blocks are ideal for sharing longer code snippets or preformatted text. To do this, you wrap your text with three backticks (&lt;code&gt;&lt;/code&gt;`&lt;code&gt;&lt;/code&gt;). To add a new line, you have to use &lt;code&gt;\n&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Throughout, we are using the &lt;a href="https://api.slack.com/block-kit"&gt;Block Kit&lt;/a&gt; to show how you build mrkdwn to use with the Slack API. Block Kit enables developers to build interactive and visually appealing messages in Slack. By incorporating mrkdwn within these blocks, you can achieve a fine balance between structure and textual presentation, ensuring your messages are not only interactive but also clear and captivating.&lt;/p&gt;

&lt;p&gt;If you are writing these into your code for a notification app, here’s how they would look:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is *bold* &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is _italic_ &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is ~strikethrough~ &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is `code` &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; ```This is a code block&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;And it's multi-line```&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This message will read in Slack as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eMk8oIrq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhdu5bkmkn6ikk7ujce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eMk8oIrq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/txhdu5bkmkn6ikk7ujce.png" alt="Slack Formatting" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The primary goal of this formatting is to enhance comprehension and draw attention to essential information. Overuse might make messages harder to read. So, while it’s tempting to jazz up every message with formatting, always prioritize clarity.&lt;/p&gt;

&lt;p&gt;You can find all the special formatting for mrkdwn in the &lt;a href="https://api.slack.com/reference/surfaces/formatting"&gt;Slack mrkdwn formatting docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Links and mentions: engaging directly with users and content
&lt;/h2&gt;

&lt;p&gt;A foundational element of Slack is that you can use notifications to directly engage individuals and teams through mentions and direct those users to specific channels, applications, or sites through links.&lt;/p&gt;

&lt;p&gt;We can split these into two types: internal Slack links and mentions and external links to sites and emails.&lt;/p&gt;

&lt;p&gt;Internally, mrkdwn uses the @ symbol to mention a specific user (such as &lt;code&gt;@colin&lt;/code&gt;) or user group, such as &lt;code&gt;@here&lt;/code&gt;, &lt;code&gt;@everyone&lt;/code&gt;, or &lt;code&gt;@channel&lt;/code&gt;. As with when you are working directly in Slack, etiquette is important here. Don’t &lt;code&gt;@everyone&lt;/code&gt; unless you really need everyone.&lt;/p&gt;

&lt;p&gt;Internal to Slack you can also highlight and direct users to other channels, using the hash symbol (#).&lt;/p&gt;

&lt;p&gt;To link away from Slack, you use hyperlinks. The format for these in mrkdwn is &lt;code&gt;&amp;lt;URL|Displayed Text&amp;gt;&lt;/code&gt;. So &lt;code&gt;&amp;lt;https://knock.app|Knock&amp;gt;&lt;/code&gt; will render as a clickable link titled “Knock” leading to &lt;a href="https://knock.app/"&gt;https://knock.app&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can use this syntax to link to an email address as well, you just prepend the email address with the mailto protocol. So &lt;code&gt;&amp;lt;mailto:hello@knock.app|hello@knock.app&amp;gt;&lt;/code&gt; will render as a clickable “&lt;a href="mailto:hello@knock.app"&gt;hello@knock.app&lt;/a&gt;” link that opens a user’s default email client with &lt;a href="mailto:hello@knock.app"&gt;hello@knock.app&lt;/a&gt; as the recipient.&lt;/p&gt;

&lt;p&gt;Here are code examples of these:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;This is a link to the &amp;lt;https://knock.app|Knock website&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is a mention of user @andrew &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is an @channel mention &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is a link to the #random channel &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; This is an email link &amp;lt;mailto:hello@knock.app|hello@knock.app&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This will show in Slack as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dwnzPTP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0qsija9jrmuhm6cgks5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dwnzPTP_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0qsija9jrmuhm6cgks5d.png" alt="Slack Taggin" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When leveraging special links and mentions, always remember to consider the context and the intended audience. While mentions are a powerful way to get someone’s attention, they can be disruptive if overused.&lt;/p&gt;

&lt;p&gt;Likewise, linking to channels or external sites should be done judiciously to ensure the message remains clear and focused.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lists and blockquotes: structuring your message
&lt;/h2&gt;

&lt;p&gt;Structuring messages lets you convey multiple points or highlight a specific piece of information. In mrkdwn, you can use lists and blockquotes to make your message more digestible.&lt;/p&gt;

&lt;p&gt;There is no particular syntax for lists within mrkdwn, at least when sending messages via the API. Instead, you can use whichever symbol you want to specify an unordered list&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;- Item 1 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; - Item 2 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; - Item 3 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; - Item 4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This renders to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VQuG_jUp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ozi7gjike0vw172l4fex.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VQuG_jUp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ozi7gjike0vw172l4fex.png" alt="Slack Unordered" width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ordered lists are just numbers or letters as the symbol. For instance:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1. Item 1 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 2. Item 2 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 3. Item 3 &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 4. Item 4&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This becomes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayjh-oG9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/weht67lqw1io52e43xzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ayjh-oG9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/weht67lqw1io52e43xzl.png" alt="Slack Ordered" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To add blockquotes to highlight or emphasize a particular section, like a quotation or important note, you start a line with &lt;code&gt;&amp;gt;&lt;/code&gt; followed by a space.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt; This is a blockquote. It can span multiple lines and is often used to highlight specific pieces of information or quotations.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This renders as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Hk4xp9Fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wrlnjx443k45f1y0j7nt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Hk4xp9Fb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wrlnjx443k45f1y0j7nt.png" alt="Slack Blockquote" width="800" height="224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While lists and blockquotes are excellent tools for enhancing readability, they should be used thoughtfully. Too many lists can confuse readers, and excessive blockquoting might dilute the emphasis you’re trying to create.&lt;/p&gt;

&lt;h2&gt;
  
  
  Special formatting: elevating your Slack messages
&lt;/h2&gt;

&lt;p&gt;There are a few other options with mrkdwn that you might need to use.&lt;/p&gt;

&lt;p&gt;First, displaying dates in a consistent, readable manner with date formatting. Here, you use the timestamp in UNIX format with the syntax &lt;code&gt;&amp;lt;!date^timestamp^{date_format}|{fallback_text}&amp;gt;&lt;/code&gt;, like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Today is: &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date_short}|Oct 13, 2023&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date_short_pretty}|Oct 13, 2023&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date_long}|Oct 13, 2023&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date_long_pretty}|Oct 13, 2023&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date_num}|Oct 13, 2023&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;!date^1697250654^{date}|Oct 13, 2023&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This renders as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--N-bqNjch--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpa7w9yafyobz1e0dbhi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--N-bqNjch--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vpa7w9yafyobz1e0dbhi.png" alt="Slack Time" width="800" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tip: In JavaScript or TypeScript, use &lt;code&gt;const unixTimestamp = Math.floor(Date.now() / 1000)&lt;/code&gt; to get the current date in UNIX format.&lt;/p&gt;

&lt;p&gt;You can also combine some of the mrkdwn above. For example, to bold a link, you can use:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Here is a *bolded* link to &amp;lt;https://knock.app|*Knock*&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Which will render a bolded link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9g-EyX98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4deyfprsk6ee8gfwwpk6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9g-EyX98--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4deyfprsk6ee8gfwwpk6.png" alt="Slack Bold Link" width="800" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And, last but definitely not least, you have emojis:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:earth_americas: :rocket: :star: :alien: :moon: :sun_with_face: :zap: :fire: :cloud: :umbrella: :rainbow: :cat: :dog: :mouse: :elephant: :tiger: :rooster: :snake:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This gives us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oLkx1j2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4je0bb53g5g2x9ywdc30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oLkx1j2I--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4je0bb53g5g2x9ywdc30.png" alt="Slack Emoji" width="800" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Remember, you can never have enough emojis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together: A mrkdwn alert
&lt;/h2&gt;

&lt;p&gt;Let’s put all this together into an alert that an application monitoring platform might send through Slack. Some elements we might use are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Notifying a specific individual or team&lt;/strong&gt;. The application might get this information from a database of SREs or on-call individuals. Here we will use &lt;code&gt;@-mentions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A concise description of the alert&lt;/strong&gt;. Here we will use basic formatting to highlight the issue.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Links to dashboards and pertinent information&lt;/strong&gt;. So the team can go deeper into the issue&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A list of steps to be taken&lt;/strong&gt;. These can be predefined and added to the Block Kit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date and time information&lt;/strong&gt;. Then anyone seeing the alert will know when the alert happened.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Emojis&lt;/strong&gt;. This can add visual appeal to the alert and draw attention to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Altogether, the mrkdwn for this alert would be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;section&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mrkdwn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@colin &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; @sres &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt; *&amp;lt;!date^1697250654^{date_num}|Oct 13, 2023&amp;gt;* &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt; *[APM ALERT]: Elevated Error Rates Detected!* :red_circle: &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; - Service: `User Authentication API` &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; - Environment: `Production` &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt; :chart_with_upwards_trend: Metrics &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt; *Error Rate*: _15%_ (Threshold: _5%_) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; *Response Time*: _900ms_ (Average: _200ms_) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; *Throughput*: _1200 rpm_ (Requests Per Minute) &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; :world_map: Geographical Impact: _US East, Europe Central_ &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; :sos: Related Incidents: &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;https://example.com|Database Latency Spike&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; &amp;lt;https://example.com|Redis Connection Failures&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; :link: *Dashboard Link*: &amp;lt;https://example.com|APM Dashboard&amp;gt; &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;  &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; :speech_balloon: Recommended Actions: &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 1. Verify backend database health and connection. &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 2. Check Redis server and related metrics. &lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt; 3. Assess recent deployments for potential issues.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This code looks complicated, but most of this information will be added dynamically from the APM. This creates a well-formatted, clear message for the team:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IjM-hnnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbab9pa1r9c6534ig54n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IjM-hnnO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xbab9pa1r9c6534ig54n.png" alt="Slack Full Notification" width="800" height="1029"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use mrkdwn for clear communication
&lt;/h2&gt;

&lt;p&gt;Slack’s mrkdwn is a powerful tool. Using mrkdwn enhances the readability and emphasis of critical pieces of information. The above example alert shows this, highlighting the crucial data for a team and making sure they can act on that information quickly.&lt;/p&gt;

&lt;p&gt;Integrating mrkdwn into your Slack notifications not only beautifies the message but, more importantly, makes it exponentially more user-friendly. When time is of the essence, and clarity is paramount, leveraging the full potential of mrkdwn ensures that your alerts are not just noticed but acted upon effectively.&lt;/p&gt;

&lt;p&gt;At Knock, we’ve taken mrkdwn further by integrating it into our &lt;a href="https://docs.knock.app/integrations/chat/slack/designing-slack-templates"&gt;templating engine&lt;/a&gt; and enhancing it with liquid tags for templating and an easy-to-use JSON editor. This allows you to design your Slack notifications exactly how you want them.&lt;/p&gt;

&lt;p&gt;Check out some &lt;a href="https://docs.knock.app/integrations/chat/slack/slack-examples"&gt;Slack notification examples&lt;/a&gt; for inspiration and sign up &lt;a href="https://dashboard.knock.app/signup"&gt;here&lt;/a&gt; to get started for free.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The top real-time notification services for building in-app notifications</title>
      <dc:creator>Colin White</dc:creator>
      <pubDate>Tue, 24 Oct 2023 20:11:29 +0000</pubDate>
      <link>https://forem.com/knocklabs/the-top-real-time-notification-services-for-building-in-app-notifications-olc</link>
      <guid>https://forem.com/knocklabs/the-top-real-time-notification-services-for-building-in-app-notifications-olc</guid>
      <description>&lt;p&gt;Real-time, in-app notifications in a product allow you to instantly engage users with relevant content, enhancing user experience and user retention. These notifications foster immediate action and feedback, ensuring users stay informed and connected to the application's latest updates and activities.&lt;/p&gt;

&lt;p&gt;But building in-app notifications from scratch is challenging. First, you have to manage the infrastructure for WebSockets and Publish/Subscribe messaging patterns to power the real-time behavior. Second, your product needs logic to deal with user preferences, user presence detection, storage, and logging. Finally, you need to build out the frontend UI features and underlying APIs to display the notifications.&lt;/p&gt;

&lt;p&gt;Using a SaaS service to offload some or all of this complexity allows you to concentrate on your own product while still giving the benefit of in-app notifications to your customers.&lt;/p&gt;

&lt;p&gt;Here, we will evaluate 4 providers to power the real-time infrastructure for your in-app notifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The key features of real-time services for in-app notifications
&lt;/h2&gt;

&lt;p&gt;What should you be looking for in a real-time service for in-app notifications?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pricing&lt;/strong&gt;: The cost-effectiveness of in-app notifications can significantly influence an app's overall budget and profitability. Transparent, scalable pricing ensures you can anticipate costs, allocate resources, and adjust any strategy based on budget.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: In-app notifications should adapt as user bases grow or shrink. A scalable notification system can handle spikes in traffic and vast volumes of concurrent users, ensuring every individual receives timely and consistent alerts without overburdening infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt;: A reliable in-app notification system guarantees that users receive messages without delays. This reliability is vital for maintaining trust, especially in applications where timely alerts can impact user decisions or safety.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Framework&lt;/strong&gt;: The chosen framework should support your desired communication mechanism, be it pub/sub for broadcasting messages to various subscribers, WebSockets for real-time bidirectional communication, or polling where the client periodically requests updates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Features&lt;/strong&gt;: Essential features to consider include presence (indicating who is online), low latency (ensuring rapid message delivery), the ability to query the state (understanding the current status of a user or system), and encryption (securing the content of the messages for privacy and protection).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer experience&lt;/strong&gt;: An intuitive and well-documented platform streamlines the integration and maintenance process for developers. A positive developer experience translates to quicker implementation, fewer bugs, and more time spent refining and enhancing the core features of the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's look at a few services and how they align with these key features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pusher
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SbxGF-pL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wllg4041l802qmptl9gi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SbxGF-pL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wllg4041l802qmptl9gi.png" alt="Pusher" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pusher.com/channels"&gt;Pusher Channels&lt;/a&gt; is a real-time notifications service that empowers developers to swiftly integrate real-time functionality, like live notifications and chat, into web and mobile apps using WebSockets. Pusher is known for reliability and scalability and is used by Buffer, GitHub, and Datadog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Managed WebSocket connections with fallback&lt;/li&gt;
&lt;li&gt;Support for Publish/Subscribe framework&lt;/li&gt;
&lt;li&gt;Presence detection&lt;/li&gt;
&lt;li&gt;The ability to query the API to find out channel and state information&lt;/li&gt;
&lt;li&gt;Interactivity through webhooks&lt;/li&gt;
&lt;li&gt;End-to-end encryption&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;. Pusher easily handles surges in traffic, ensuring consistent real-time communication for applications ranging from startups to large enterprises.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Versatility&lt;/strong&gt;. With SDKs for various languages and platforms, Pusher seamlessly integrates with numerous tech stacks, simplifying real-time feature implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliable WebSocket fallback&lt;/strong&gt;. Pusher's automatic fallback mechanisms guarantee continuous connectivity, even when WebSockets are unsupported or unstable.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Location.&lt;/strong&gt; You are locked into a specific data center location when you sign up for Pusher and “it's not possible to change it afterwards.” This means that notification latency will slow further from the data center location.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing complexity&lt;/strong&gt;. With eight tiers and pricing changing with messages, connections, and support, it is not clear how you'll have to pay. You also have to pay separately for Pusher Beams, their Push notification service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;Pusher has &lt;a href="https://pusher.com/channels/pricing/"&gt;eight pricing tiers&lt;/a&gt; ranging from free on the “Sandbox” tier, where you get 200k messages per day and 100 concurrent connections, standard support and no monitoring, to $1,199/month on the “Growth Plus” tier for 90 million messages per day and 30,000 concurrent connections with premium support and monitoring. After that, you can contact the team for enterprise-level pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  PubNub
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nUtmm7AE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ok4wcgeqzxomk7y5as4f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nUtmm7AE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ok4wcgeqzxomk7y5as4f.png" alt="PubNub" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.pubnub.com/"&gt;PubNub&lt;/a&gt; is a real-time communication platform based on HTTP long-polling instead of WebSockets. It provides scalable infrastructure to send and receive messages at low latency, and supports presence, compression, and storage. Customers include Niantic, Kustomer, and Autodesk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses the Publish/Subscribe framework to send high volumes of messages&lt;/li&gt;
&lt;li&gt;Low latency messaging&lt;/li&gt;
&lt;li&gt;GZip message compression&lt;/li&gt;
&lt;li&gt;Message persistence for history through their storage API&lt;/li&gt;
&lt;li&gt;Presence detection&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Broad integration options&lt;/strong&gt;. PubNub offers SDKs for numerous platforms and languages, making integration effortless across various development environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust feature set&lt;/strong&gt;. Beyond just messaging, PubNub provides presence detection, storage, and playback, catering to diverse real-time app requirements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High scalability&lt;/strong&gt;. Built for large-scale applications, PubNub can handle millions of concurrent connections without compromising performance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pricing concerns&lt;/strong&gt;. As message volumes or connections increase, costs can escalate due to usage-based pricing, making budgeting unpredictable for high-traffic applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lack of WebSockets&lt;/strong&gt;: PubNub uses the Publish/Subscribe model across HTTP rather than WebSockets. WebSockets have better scalability, better error handling, and lower latencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.pubnub.com/pricing/"&gt;PubNub&lt;/a&gt; has a free tier giving users up to 200 MAUs or 1M total transactions per month. They are clear that this is for testing purposes only and should not be used for production. For production-level applications, they have a $49/month tier that allows up to 1000 MAUs and 3000 transactions per MAU. Usage-based billing is used beyond those limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ably
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mmu0PK69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfw9wpfmak2wikm09tdm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mmu0PK69--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dfw9wpfmak2wikm09tdm.png" alt="Ably" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ably.com/"&gt;Ably&lt;/a&gt; is a robust real-time data delivery platform based on WebSockets with features like message ordering, presence, and connection recovery. Customers include Toyota, HubSpot, and Verizon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Low latencies of ~65ms for notification delivery&lt;/li&gt;
&lt;li&gt;Queryable state API to find popular channels and user presence&lt;/li&gt;
&lt;li&gt;Reduced bandwidth with delta compression&lt;/li&gt;
&lt;li&gt;Also supports MQTT and server-side events as well as WebSockets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connection State Recovery&lt;/strong&gt;: Ensures interrupted users can resume their session without missing data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Consistency&lt;/strong&gt;: Guaranteed message ordering and delivery ensure that all users receive updates in the correct sequence.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge network&lt;/strong&gt;. Ably uses 15 data centers around the globe and persists data across each to lower latencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pricing Model&lt;/strong&gt;: With a pay-as-you-go model, costs can escalate quickly with little control if you add more users and channels.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://ably.com/pricing"&gt;Ably pricing&lt;/a&gt; has a free tier offering 6M monthly messages across 200 concurrent channels and 200 concurrent connections. They then move to a pay-as-you-go model which charges $2.50 per million messages, $15.00 per thousand concurrent channels, and $15.00 per thousand concurrent connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="http://socket.io/"&gt;Socket.io&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5LuKIjvK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5rt5fzy1nvapbwy3cfn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5LuKIjvK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5rt5fzy1nvapbwy3cfn.png" alt="Socket.io" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://socket.io/"&gt;Socket.io&lt;/a&gt; is an open-source JavaScript library that facilitates real-time web communication. It simplifies bidirectional data transfer between web clients and servers. By abstracting WebSockets with fallbacks, it ensures consistent performance across devices and browsers, making real-time chats, notifications, and dynamic content more accessible for developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatic reconnection&lt;/li&gt;
&lt;li&gt;Middleware to filter and act on incoming packets&lt;/li&gt;
&lt;li&gt;Built-in support for binary data.&lt;/li&gt;
&lt;li&gt;Multiplexing through multiple namespaces&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of use&lt;/strong&gt;: Socket.io offers a simple API, enabling developers to quickly integrate real-time functionalities without deep expertise in WebSockets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-platform&lt;/strong&gt;: It provides client-side libraries for multiple platforms, ensuring broad compatibility across devices and browsers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fallback mechanisms&lt;/strong&gt;: If WebSockets aren't available, Socket.io automatically falls back to other methods, ensuring consistent connectivity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability concerns&lt;/strong&gt;: For very large-scale applications, Socket.io might face challenges, requiring additional configurations or optimizations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosting&lt;/strong&gt;: As Socket.io is only a library, you have to set up the infrastructure yourself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pricing
&lt;/h3&gt;

&lt;p&gt;N/A. Socket.io is an open-source library that allows you to build real-time communication more easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the right solution
&lt;/h2&gt;

&lt;p&gt;The above options are great choices for providing the backend infrastructure for real-time notifications. But if you want to use these real-time services as the foundation for in-app notifications, then you’ll have to think about what needs to be built around them. These options don’t feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UI components&lt;/strong&gt;. While these services provide the backend infrastructure for notifications, they don't typically offer ready-to-use frontend components, meaning you'd need to design and implement the visual aspects of your notifications separately.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Templated messaging&lt;/strong&gt;. You may need to build or integrate a system that allows for templated messages, letting you send consistent yet customizable notifications based on predefined templates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Read receipts&lt;/strong&gt;. Knowing if and when a user has seen a message can be vital for engagement and user experience. These platforms might not offer out-of-the-box solutions for read receipts, necessitating additional development.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactivity&lt;/strong&gt;. These services deliver messages, but enabling interactive elements (e.g., buttons or links within notifications) would require additional development and design efforts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User preferences&lt;/strong&gt;. Tailoring notifications to user preferences, such as frequency, type, or topic, is crucial for a positive user experience. Incorporating such customization would need a separate mechanism or system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these will have to be built out for a complete in-app notification system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Introducing notification infrastructure
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://knock.app/"&gt;Knock&lt;/a&gt; is a developer tool for building cross-channel notification systems. You can use it to add in-app notifications to your app with pre-built components to get you started quickly, but the power comes from integrating in-app and out-of-app channels such as email, push, SMS, and Slack. You can build workflows for these notifications so the right messages are sent via the right channels to the right users at the right time. We built Knock to be the best option for teams needing to implement any type of notification in their application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X5R1y5M7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p4aqy2do775zesfia3e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X5R1y5M7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3p4aqy2do775zesfia3e.png" alt="Knock" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Knock also takes care of all of your retry and delivery logic, as well as &lt;a href="https://docs.knock.app/designing-workflows/batch-function"&gt;batching&lt;/a&gt; (collapsing multiple notifications about a single topic into one), managing &lt;a href="https://knock.app/features/preferences"&gt;per-user notification preferences&lt;/a&gt;, and providing &lt;a href="https://knock.app/features/observability"&gt;unparalleled visibility into the notifications your product is sending&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://knock.app/"&gt;Knock&lt;/a&gt; is an all-in-one notification platform that allows developers to build stateful, in-app notification experiences like floating feeds, inboxes, toasts and banners. Customers include &lt;a href="https://knock.app/customers/vercel"&gt;Vercel&lt;/a&gt;, &lt;a href="https://knock.app/customers/amplitude"&gt;Amplitude&lt;/a&gt;, and &lt;a href="https://knock.app/customers/darwin-homes"&gt;Darwin Homes&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Pre-built components to power in-app notifications that can be customized to match your brand&lt;/li&gt;
&lt;li&gt;No infrastructure setup, no APIs to build&lt;/li&gt;
&lt;li&gt;Workflow builder to determine how to alert users&lt;/li&gt;
&lt;li&gt;Visual template builder to create and update notification templates&lt;/li&gt;
&lt;li&gt;Preferences API to let users take control of their notifications&lt;/li&gt;
&lt;li&gt;Strong support with responses in hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd like to try it out, you can &lt;a href="https://dashboard.knock.app/signup"&gt;sign up for a free account&lt;/a&gt; and get started by checking out our &lt;a href="https://docs.knock.app/in-app-ui/overview"&gt;in-app feed docs&lt;/a&gt;. 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>tooling</category>
    </item>
    <item>
      <title>The 7 best transactional email services for developers in 2023</title>
      <dc:creator>Colin White</dc:creator>
      <pubDate>Thu, 19 Oct 2023 14:54:57 +0000</pubDate>
      <link>https://forem.com/knocklabs/the-7-best-transactional-email-services-for-developers-in-2023-584j</link>
      <guid>https://forem.com/knocklabs/the-7-best-transactional-email-services-for-developers-in-2023-584j</guid>
      <description>&lt;p&gt;If your application needs to send transactional emails, you'll need a transactional email provider to deliver those emails on your behalf. In this article, we evaluate our favorite seven transactional email service providers you can use as a developer in 2023.&lt;/p&gt;

&lt;p&gt;Let's get to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 7 best transactional email APIs for developers
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://sendgrid.com/"&gt;SendGrid&lt;/a&gt;. An industry-leading email API with good deliverability and a comprehensive suite of analytics.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://postmark.com/"&gt;Postmark&lt;/a&gt;. Fantastic deliverability, a well-designed API, and a cost-effective solution for ensuring that your transactional messages get to your customers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/ses/"&gt;AWS SES&lt;/a&gt;. A highly reliable and scalable option for those who are already within the AWS ecosystem.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mailgun.com/"&gt;Mailgun&lt;/a&gt;. A developer-focused, scalable, and reliable email sending service.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://resend.com"&gt;Resend&lt;/a&gt;. Great for developers looking to build and send transactional emails with React or Next.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mailchimp.com/features/transactional-email/"&gt;MailChimp Transactional (formerly Mandrill)&lt;/a&gt;. Sold as a paid Mailchimp add-on. If you're already a user of Mailchimp to send marketing announcements, this is a good option.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sparkpost.com/"&gt;Sparkpost&lt;/a&gt;. Good deliverability and a robust set of analytics tools make this a solid choice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why you should trust us
&lt;/h2&gt;

&lt;p&gt;We're &lt;a href="https://knock.app"&gt;Knock&lt;/a&gt; and we're a developer tool for building production-grade, cross-channel notification systems. &lt;/p&gt;

&lt;p&gt;We've built integrations with 20+ different notification providers, spent hundreds of hours working with (and discovering the intricacies of) their APIs, and seen up-close how they perform at scale across a wide range of use cases. Today Knock powers production notifications for Vercel, Teikametrics, and SafetyCulture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes a great transactional email service?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pricing and value.&lt;/strong&gt; Cost matters. You want to ensure there's a free tier you can use to "kick the tires" of the service, and understand how the pricing scales as you start sending larger volumes of emails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deliverability.&lt;/strong&gt; You're using a transactional email service so you don't have to think about deliverability. It's paramount that the transactional email service you use has high deliverability and gets emails to your customer's inbox in a timely fashion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of use.&lt;/strong&gt; Integrating the service into your product should not be a burden, there should be simple instructions and a sane, easy-to-understand set up process to send your first email with the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation and SDKs.&lt;/strong&gt; As developer-focused services, these providers must have well-designed API and SDKs available in most major languages. Great documentation is also essential, helping you get the support and guidance you need if you get stuck during setup.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics.&lt;/strong&gt; Emails generate "exhaust data" for engagement data such as opens and clicks, as well as deliverability data. The service should easily give access to this data, and ideally, make it accessible via a dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We take an in-depth look at seven transactional email services using the above criteria as a guide to determine how the services stack up against each other. We've created an account on each service, set up a domain, and triggered emails to be sent to see how each service &lt;em&gt;really&lt;/em&gt; performs.&lt;/p&gt;

&lt;p&gt;As an aside, we used &lt;a href="https://knock.app"&gt;Knock&lt;/a&gt; here as a way to quickly integrate the transactional email service, build an email template, and send a test email through each service, without needing to write service-specific integration code. Knock can also take care of managing our email templates, giving us cross-provider analytics, and sending cross-channel notifications to other in-app and out-of-app channels like push, SMS, and Slack. &lt;/p&gt;

&lt;h2&gt;
  
  
  SendGrid
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZEqh9iDV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1o937qic6mkjds8ovko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZEqh9iDV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j1o937qic6mkjds8ovko.png" alt="Sendgrid website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SendGrid is a widely-used email service from Twilio used by internet giants such as Uber, Booking.com, and Yelp to send and deliver their transactional emails. SendGrid is an excellent option for teams that want to get started quickly and have an email service that will scale with them over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  SendGrid features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Comes with outbound (sending) and inbound (receiving) APIs.&lt;/li&gt;
&lt;li&gt;Supports attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Support for dedicated IP addresses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sendgrid.com/solutions/email-api/email-address-validation-api/"&gt;Email address validation API&lt;/a&gt;. Note: this is billed separately from email sends.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://sendgrid.com/solutions/email-api/dynamic-email-templates/"&gt;Template management&lt;/a&gt;, including a visual template editor and a streamlined version control and approval process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Great documentation and SDK support.&lt;/strong&gt; &lt;a href="https://docs.sendgrid.com/"&gt;SendGrid's documentation&lt;/a&gt; is easy to navigate, and &lt;a href="https://docs.sendgrid.com/for-developers/sending-email/api-getting-started"&gt;the quick start guides&lt;/a&gt; make it easy to get integrated quickly. There's also SDKs available for &lt;a href="https://docs.sendgrid.com/for-developers/sending-email/libraries"&gt;most major languages&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rich analytics tools.&lt;/strong&gt; SendGrid has a full suite of tools for &lt;a href="https://sendgrid.com/solutions/email-api/deliverability-insights/"&gt;monitoring and reporting on email insights&lt;/a&gt;. They also offer programmatic access to this data via their API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A focus on deliverability and scale.&lt;/strong&gt; SendGrid has a &lt;a href="https://sendgrid.com/email-delivery/"&gt;number of tools to help with deliverability&lt;/a&gt; and makes this a core focus of their product, which includes their recent investment into &lt;a href="https://sendgrid.com/blog/building-artificial-intelligence-into-sendgrid-our-journey-so-far-and-what-it-means-for-you/"&gt;A.I. powered intelligent delivery&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email sending history is a paid add-on.&lt;/strong&gt; SendGrid offers an extended email activity history add-on that grants access to 30 days of sending history, as well as API access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SendGrid pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://sendgrid.com/pricing/"&gt;SendGrid offers 4 tiers of pricing&lt;/a&gt;: Free, Essentials, Pro, and Premier. The free plan offers 100 emails/day, while the Essentials plan starts at $19.95/month and includes 50,0000 emails each month with overages charged on top. Dedicated IP addresses email validations are available in the Pro plan and above. Volume based discounts are available on the Premier plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Postmark
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6zEUkB_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69x6eai5myn5nilpdvb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6zEUkB_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/69x6eai5myn5nilpdvb0.png" alt="Postmark website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://postmark.com/"&gt;Postmark&lt;/a&gt; is a transactional email service from ActiveCampaign that prides itself on its inbox deliverability. Compared to some of the offerings in this post, Postmark has a smaller set of customers but is still trusted to power emails for 1Password, Paddle, and Webflow. If you're looking for a no-nonsense service that focuses on deliverability, Postmark is an excellent choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  Postmark features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Comes with outbound (sending) and inbound (receiving) APIs.&lt;/li&gt;
&lt;li&gt;Supports attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Support for dedicated IP addresses.&lt;/li&gt;
&lt;li&gt;45-day message and log retention on all plans.&lt;/li&gt;
&lt;li&gt;Offers a paid &lt;a href="https://dmarcdigests.com/"&gt;DMARC monitoring service&lt;/a&gt; that you can use to track your email sending reputation and proactively address any issues ($10/domain/month).&lt;/li&gt;
&lt;li&gt;Support for &lt;a href="https://postmarkapp.com/developer/webhooks/webhooks-overview"&gt;webhooks&lt;/a&gt; for receiving and processing engagement and delivery events to synchronize with your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Postmark also offers a comprehensive dashboard that you can use to look at &lt;a href="https://postmarkapp.com/email-analytics"&gt;message-sending and engagement analytics data&lt;/a&gt;, as well as creating and maintaining &lt;a href="https://postmarkapp.com/email-templates"&gt;email templates&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deliverability.&lt;/strong&gt; Postmark consistently has excellent inbox deliverability when compared to some of the other major providers referenced in this post. They relentlessly focus on having &lt;a href="https://postmarkapp.com/email-delivery"&gt;great deliverability&lt;/a&gt; for transactional emails, and run separate infrastructure for any bulk campaign messages to ensure your transactional emails get to your users' inboxes in a timely manner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Visibility into time-to-inbox data.&lt;/strong&gt; Postmark &lt;a href="https://tti.postmarkapp.com/"&gt;publish data on time-to-inbox&lt;/a&gt;, a metric that's tracked and aggregated across major email providers to document the time between sending an email and it being available within a user's inbox (i.e. delivered).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great documentation and SDKs for all major languages.&lt;/strong&gt; As a developer-focused tool, Postmark has a fantastic set of &lt;a href="https://postmarkapp.com/developer"&gt;API documentation&lt;/a&gt; and guides, as well as a &lt;a href="https://postmarkapp.com/developer/integration/official-libraries"&gt;wide range of official&lt;/a&gt; and &lt;a href="https://postmarkapp.com/developer/integration/community-libraries"&gt;community-supported SDKs&lt;/a&gt; available for all major languages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lack luster templating.&lt;/strong&gt; While Postmark does support some templating within their product, the offering is less robust than some of the other services listed in this post (notably SendGrid and SparkPost) given they don't offer a visual, drag-and-drop editor.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Postmark pricing
&lt;/h3&gt;

&lt;p&gt;Postmark offers a &lt;a href="https://postmarkapp.com/pricing"&gt;simple tiered-volume pricing&lt;/a&gt; that's billed monthly. Each plan tier includes a base amount of emails per month, and overages are charged by the thousand at a sliding scale depending on the volume sent. There's also a free developer plan that provides 100 test emails every month for free if you want to try out the service.&lt;/p&gt;

&lt;p&gt;Dedicated IP addresses are available for customers sending over 300,000+ emails a month for $50/month.&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS Simple Email Service (SES)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mRlqZ6KW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bs2hvp3u5adjphjj7uy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mRlqZ6KW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2bs2hvp3u5adjphjj7uy.png" alt="AWS SES website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/ses/"&gt;AWS Simple Email Service&lt;/a&gt; (SES) touts itself as "a cost-effective, flexible, and scalable email service". It's a product offering from Amazon Web Services and is designed to send high volumes of transactional emails. AWS SES is lighter on features than some of the other services we're comparing in this list, but if you're already deployed within AWS or use any other products within the AWS suite it might be worth considering as an option.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS SES Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Inbound (receiving) and outbound (sending) are supported via the API and SDKs.&lt;/li&gt;
&lt;li&gt;Attachments are supported via the &lt;a href="https://docs.aws.amazon.com/ses/latest/dg/send-email-raw.html"&gt;raw email sending API&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Options for static IPs including shared, bring your own, and dedicated IP addresses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Tight integration with other AWS services such as &lt;a href="https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-targets.html"&gt;EventBridge&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/ses/latest/dg/monitor-using-event-publishing.html"&gt;Cloudwatch&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Support for tracking deliverability metrics such as bounces, complaints, and delivery rates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Deliverability at an enormous scale.&lt;/strong&gt; SES sends hundreds of billions of emails a year for some of the largest internet companies on earth, such as Netflix, Reddit, and Amazon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDKs in all major languages.&lt;/strong&gt; The &lt;a href="https://aws.amazon.com/developer/tools/"&gt;AWS SDK&lt;/a&gt; is available in all major server-side languages along with &lt;a href="https://docs.aws.amazon.com/ses/index.html"&gt;thorough accompanying documentation&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Setup is complex.&lt;/strong&gt; As is the case with many AWS services, getting started with SES can be daunting. The documentation and examples often leave a lot to be desired, with auto-generated SDKs and docs making it difficult to understand exactly how the API works.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All accounts are initially sandboxed.&lt;/strong&gt; This limits initial sending to 200 messages in a 24-hour period, with restrictions on who can be sent an email (allow listed domains and email addresses). The sandbox restriction can be removed from the &lt;a href="https://console.aws.amazon.com/ses/"&gt;SES console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessing analytics data is non-trivial.&lt;/strong&gt; To access analytics data (opens, link clicks, deliverability metrics) you need to add an SNS topic to route all events through and then have a destination (like a lambda function) to process the event.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS SES pricing
&lt;/h3&gt;

&lt;p&gt;AWS SES is one of the cheapest options for sending emails out there. If your application is already hosted in AWS, then the first 62,000 emails sent each month is free. Beyond that volume emails are priced at $0.10 for every 1,000 emails sent and $0.12 for each GB of attachment data. On the inbound side, the first 1,000 emails are free and then it's $0.10/per 1,000 emails received.&lt;/p&gt;

&lt;p&gt;As an aside, it's important to note that with SES, like most AWS services, you will pay for outgoing data and transfer fees:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“You pay for outgoing mail data, incoming mail chunks, and EC2 data transfer fees—even if your usage of Amazon SES qualifies for the AWS Free Usage Tier.“&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Pricing with SES can get complicated, so it's probably best if you use the &lt;a href="https://aws.amazon.com/ses/pricing/#Pricing_calculator"&gt;AWS SES pricing calculator&lt;/a&gt; to understand exactly how much the service will cost you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mailgun
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QaUXYL9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scbsga9ixdwznxokq4pr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QaUXYL9z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/scbsga9ixdwznxokq4pr.png" alt="Mailgun website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mailgun.com"&gt;Mailgun&lt;/a&gt; from Sinch is a well-established, developer-focused email service that's been in business since 2010. It powers email delivery for some large, well-known companies including Lyft, American Express, and Wikipedia. As a developer-focused tool, Mailgun is fast to get started with and integrate into your product. It's an excellent offering if you're looking for a reliable, easy-to-use product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mailgun features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Comes with outbound (sending) and inbound (receiving) APIs.&lt;/li&gt;
&lt;li&gt;Supports attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Support for dedicated IP addresses and dedicated IP address pools on higher tiers of sending.&lt;/li&gt;
&lt;li&gt;Has advanced features such as &lt;a href="https://www.mailgun.com/products/send/send-time-optimization/"&gt;send time optimization&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Both EU and US-specific sending regions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.mailgun.com/products/inbox/email-verification/"&gt;Email address verification tools&lt;/a&gt;. Note: these are charged separately from your email sends.&lt;/li&gt;
&lt;li&gt;Support for &lt;a href="https://documentation.mailgun.com/en/latest/api-webhooks.html"&gt;webhooks&lt;/a&gt; for receiving and processing engagement and delivery events to synchronize with your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, Mailgun also comes with a dashboard that you can use to look at emails sent and analytics around engagement and delivery data. The dashboard also allows you to create and maintain email templates using the visual email editor available &lt;a href="https://www.mailjet.com/"&gt;via Mailjet&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excellent documentation.&lt;/strong&gt; As a developer-focused offering, Mailgun has a very well-written &lt;a href="https://documentation.mailgun.com/en/latest/quickstart.html"&gt;set of documentation&lt;/a&gt; and &lt;a href="https://www.mailgun.com/resources/guides/"&gt;guides&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Robust support for deliverability.&lt;/strong&gt; Mailgun prides itself on its commitment to deliverability &lt;a href="https://www.mailgun.com/products/inbox/deliverability-services/"&gt;with services to pair you with an email expert&lt;/a&gt; to ensure you're achieving exceptional deliverability. There's even a &lt;a href="https://documentation.mailgun.com/en/latest/best_practices.html"&gt;great section in their documentation&lt;/a&gt; for email best practices for deliverability and sending health.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lack of SDK support.&lt;/strong&gt; Mailgun has &lt;a href="https://documentation.mailgun.com/en/latest/libraries.html"&gt;SDKs available&lt;/a&gt; in most major languages but has some notable exceptions for their official SDKs including Python, Node, and Elixir.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mailgun pricing
&lt;/h3&gt;

&lt;p&gt;Mailgun comes with a generous trial tier that includes 5,000 emails included for the first 30 days. Extra sending volume is purchased in blocks of $1.00 per 1,000 messages. There are also paid tiers available that include a base amount of usage each month, with overages charged beyond the base amount. You can learn more and estimate your usage on &lt;a href="https://www.mailgun.com/plans-and-pricing/"&gt;their pricing page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;All Mailgun plans include 99.99% uptime, 24/7 support, and analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resend
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h7_PtneW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b2vcv0ic5abcgqexlf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h7_PtneW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7b2vcv0ic5abcgqexlf5.png" alt="Resend website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://resend.com"&gt;Resend&lt;/a&gt; is a new transactional email service that was in the W23 batch of Y Combinator. As a relatively new player in the email API space, the feature set offered is limited but the (excellent) team at Resend are &lt;a href="https://resend.com/docs/changelog"&gt;shipping new features&lt;/a&gt; each week to build out the service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resend features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Outbound sending only (no inbound parsing, yet).&lt;/li&gt;
&lt;li&gt;Attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;Support for dedicated IP addresses via an add-on.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Created and maintain &lt;a href="https://react.email"&gt;react email&lt;/a&gt;, a transactional email building framework for React.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Resend also comes with a dashboard that you can use to configure the service, view some statistics about the number of messages sent, see API logs for inbound requests, and logs of messages generated.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Beautiful documentation and guides.&lt;/strong&gt; The &lt;a href="https://resend.com/docs/introduction"&gt;Resend documentation&lt;/a&gt; is well-made, easy to follow, and showcases the team's attention to detail with all things developer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep integration with React.&lt;/strong&gt; If you're looking to write transactional email templates in React, there's no easier way to send those emails than with &lt;a href="https://resend.com/docs/send-with-nextjs#send-email-using-react"&gt;Resend's JavaScript SDK&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No templating support.&lt;/strong&gt; Unlike a lot of the other email services in this list, there's no option in Resend to manage templates inside of the dashboard and reference them from the API. This might not be a deal-breaker however, as long as you're comfortable maintaining your templates in your codebase.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resend pricing
&lt;/h3&gt;

&lt;p&gt;Resend offer 3 pricing tiers: Free, Pro, and Enterprise. The free tier comes with 100 emails a month which must be sent from a verified sender. The pro tier offers a usage based plan, where 50,000 emails is $20/month. Each plan comes with different lengths of data retention for sent messages and logs. The Pro plan can be upgraded with a dedicated IP for $30/month, while the Enterprise plan comes with dedicated IPs out-of-the-box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mailchimp Transactional Email (formerly known as Mandrill)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--el4Z4zIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsnjnhggmcpwv46cpwf3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--el4Z4zIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsnjnhggmcpwv46cpwf3.png" alt="Mailchimp website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mailchimp.com/features/transactional-email/"&gt;Mailchimp Transactional Email&lt;/a&gt; is an email service that's an add-on to the ever popular marketing tool, Mailchimp. It used to be called Mandrill, but in recent years has moved from a standalone service offering to a paid add-on where you must have an existing Mailchimp subscription and plan to use the service. As such, it's an ideal offering if you're an existing Mailchimp customer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mailchimp Transactional features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Comes with outbound (sending) and inbound (receiving) APIs.&lt;/li&gt;
&lt;li&gt;Supports attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Support for dedicated IP addresses.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mandrill.zendesk.com/hc/en-us/articles/360038729533-What-is-the-rules-engine-"&gt;An advanced rules engine&lt;/a&gt; to apply rules to inbound or outbound emails.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://mailchimp.com/developer/transactional/docs/webhooks/"&gt;Webhooks&lt;/a&gt; for email events, so you can respond to engagement and delivery events in real-time from your system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excellent documentation.&lt;/strong&gt; Mailchimp has some of the friendliest and best laid out &lt;a href="https://mailchimp.com/developer/transactional/api/"&gt;developer documentation&lt;/a&gt; out there, making it really easy to get up-and-running and find answers to any questions about the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong focus on deliverability and speed of delivery.&lt;/strong&gt; Mailchimp has a set of &lt;a href="https://mailchimp.com/features/transactional-email-infrastructure/"&gt;global infrastructure&lt;/a&gt; that's employed to deliver emails quickly, while ensuring great deliverability. There's also support for IP address warming, dedicated IP addresses, and IP address pools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solid analytics and reporting capabilities.&lt;/strong&gt; The dashboard has the ability to pull reports on deliverability, opens, clicks, bounces, and rejections. There are also logs that can be searched for outgoing messages by tags and subject lines.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Requires an existing Mailchimp subscription.&lt;/strong&gt; As mentioned above, Mailchimp transactional requires an existing Mailchimp Standard or Premium subscription in order to purchase the add on and start sending transactional messages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Mailchimp Transactional pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mailchimp.com/pricing/transactional-email/"&gt;Mailchimp's Transactional pricing&lt;/a&gt; is based around the concept of blocks, where each block is a credit for 25,000 emails. Blocks are charged on a sliding scale, where the more blocks that are purchased the lower the cost per block. For example, to send 100,000 emails a month the cost will be $80. In addition, there's also a free plan available to new transactional email users with 500 free email sends included to a verified domain, and you can purchase a dedicated IPs for $29.95/month.&lt;/p&gt;

&lt;p&gt;Please note: you &lt;strong&gt;will need a Mailchimp account on the Standard or Premium plan&lt;/strong&gt; to use Mailchimp Transactional Emails.&lt;/p&gt;

&lt;h2&gt;
  
  
  SparkPost
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NPquzu8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zh9nebi8d1i33s4qyt00.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NPquzu8h--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zh9nebi8d1i33s4qyt00.png" alt="SparkPost website" width="800" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sparkpost.com"&gt;SparkPost&lt;/a&gt; is an enterprise-grade email service from MessageBird that sends 37% of all emails for B2B and B2C applications. It's used by Twitter, Pinterest, and Zillow to reliably send and deliver emails. Although SparkPost is an enterprise-grade service, it's also accessible to teams at all sizes and prices very competitively.&lt;/p&gt;

&lt;h3&gt;
  
  
  SparkPost features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Comes with outbound (sending) and inbound (receiving) APIs.&lt;/li&gt;
&lt;li&gt;Supports attachments via easy-to-use, base64 encoded content.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail"&gt;DKIM&lt;/a&gt;, &lt;a href="https://en.wikipedia.org/wiki/DMARC"&gt;DMARC&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework"&gt;SPF&lt;/a&gt; supported.&lt;/li&gt;
&lt;li&gt;Dedicated IP addresses, IP address pools, and IP address warming.&lt;/li&gt;
&lt;li&gt;Support for &lt;a href="https://support.sparkpost.com/docs/tech-resources/webhook-event-reference/"&gt;webhooks&lt;/a&gt; for receiving and processing engagement and delivery events to synchronize with your system (note: there are a limited number of available webhooks on the starter and premier plans).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Pros
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Support for subaccounts.&lt;/strong&gt; If you have multiple applications that need isolated sending streams, but you want to bill them under a single consolidated account, then SparkPost's &lt;a href="https://support.sparkpost.com/docs/user-guide/subaccounts/"&gt;subaccounts&lt;/a&gt; are a useful feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-premise mail sender.&lt;/strong&gt; SparkPost is the only provider that offers an &lt;a href="https://www.sparkpost.com/powermta/"&gt;on-premise mail sending solution&lt;/a&gt; for very high volume workloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great analytics tools.&lt;/strong&gt; SparkPost includes a whole host of analytics tools to understand delivery rates, including a &lt;a href="https://www.sparkpost.com/docs/reporting/health-score/"&gt;predictive health score&lt;/a&gt; for your emails.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Excellent template management tools.&lt;/strong&gt; There are a whole suite of template management tools built into SparkPost.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Cons
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hard-to-navigate documentation.&lt;/strong&gt; While SparkPost has pretty comprehensive documentation, it's not always easy to navigate around find the specific answers your looking for. The getting started guides are also less comprehensive and beginner-friendly than some of the other services mentioned in this article.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  SparkPost pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.sparkpost.com/pricing/"&gt;SparkPost offer 3 tiers of pricing&lt;/a&gt;: Starter, Premier, and Enterprise. There's also a free developer trial available that can be used to try out features before signing up for a paid plan. The Premier and Enterprise plans are available when your monthly volume exceeds 100,000 emails/month, with both including a Dedicated IP address as part of the plan. For much higher volumes, an Enterprise plan is available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Knock to build a transactional notification system
&lt;/h2&gt;

&lt;p&gt;Adding transactional email support to your product is usually one of the first steps to building out more notifications from your product, but before long you may find yourself in the weeds building lots of different types of notifications across disparate channels. This is where &lt;a href="https://knock.app"&gt;Knock&lt;/a&gt; can help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ivH0eZ-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfafl3ux7im3ufwhdfpo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ivH0eZ-1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kfafl3ux7im3ufwhdfpo.png" alt="Knocks notification workflow engine" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://knock.app"&gt;Knock&lt;/a&gt; is a developer tool for building cross-channel notification systems. With Knock, you can create complex cross-channel notifications for your product without writing complex notification code yourself. You call Knock's API and you can send notifications to in-app and out-of-app channels such as email, push, SMS, and Slack.&lt;/p&gt;

&lt;p&gt;Even if you're only planning on sending emails from your product, Knock can help. You can use Knock's dashboard to &lt;a href="https://knock.app/features/template-management"&gt;collaboratively manage your email templates&lt;/a&gt;, either with a drag-and-drop visual builder or by dropping down to writing HTML. Knock also takes care of all of your retry and delivery logic, as well as &lt;a href="https://docs.knock.app/designing-workflows/batch-function"&gt;batching&lt;/a&gt; (collapsing multiple notifications about a single topic into one), managing &lt;a href="https://knock.app/features/preferences"&gt;per-user notification preferences&lt;/a&gt;, and providing &lt;a href="https://knock.app/features/observability"&gt;unparalleled visibility into the notifications your product is sending&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you'd like to try it out, you can &lt;a href="https://dashboard.knock.app/signup"&gt;sign up for a free account&lt;/a&gt; or &lt;a href="https://dev.to/contact-sales"&gt;chat with our team&lt;/a&gt;. 👋&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
      <category>tooling</category>
    </item>
    <item>
      <title>📈 A/B testing with limited data at a startup</title>
      <dc:creator>Colin White</dc:creator>
      <pubDate>Fri, 23 Mar 2018 18:12:39 +0000</pubDate>
      <link>https://forem.com/manifold/-ab-testing-with-limited-data-at-astartup-1i7b</link>
      <guid>https://forem.com/manifold/-ab-testing-with-limited-data-at-astartup-1i7b</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzx4fhemr7t189ekkx70m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzx4fhemr7t189ekkx70m.png" alt="A/B testing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally posted on &lt;a href="https://blog.manifold.co/a-b-testing-with-limited-data-at-a-startup-6fe1cf46f63d" rel="noopener noreferrer"&gt;Manifold&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  📈 A/B testing with limited data at a startup
&lt;/h1&gt;

&lt;p&gt;Practically every article you read about startup marketing stresses the importance of A/B testing. From the header on your landing page to the colour of your signup button, even the most minor thing should be tested. But, almost all of these articles you’re reading assume one thing. That you’re in growth mode.&lt;/p&gt;

&lt;p&gt;But that’s an issue for a lot of companies.&lt;/p&gt;

&lt;p&gt;Startups that haven’t hit growth just don’t have enough data to run A/B tests at scale. This means that testing at low numbers is a completely different ballpark than when you are scaling. I’m not saying that it’s impossible, but I’ll break down some common misconceptions and mistakes that are easy to make when testing with small amounts of data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let’s quickly define A/B testing
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A marketing experiment where two variations of a landing page, ad, email or other piece of online content are pitted against each other to determine which produces the highest conversion rate. &lt;br&gt;
&lt;a href="https://unbounce.com/conversion-glossary/definition/ab-testing/" rel="noopener noreferrer"&gt;https://unbounce.com/conversion-glossary/definition/ab-testing/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s the definition from a marketers point of view. Pit two pieces of marketing material against each other to see which converts better. This definition doesn’t do justice to the statistical methods behind A/B testing.&lt;/p&gt;

&lt;p&gt;When you run an A/B test, you are most likely doing a comparison of two binomial distributions using some type of statistical test (there are a few possibilities).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Things like click-through rates or conversion rates are binomial distributions.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you are using A/B testing software like Optimizely, a lot of these statistics are hidden from you, which can sometimes be to your detriment.&lt;/p&gt;

&lt;h2&gt;
  
  
  A/B testing pitfalls
&lt;/h2&gt;

&lt;p&gt;Testing software makes running experiments approachable to all types of people. You really don’t have to know much about statistics to pull off an A/B test in Google Optimize or Optimizely. But not having much knowledge in stats can lead you down the path to some easy to avoid mistakes.&lt;/p&gt;

&lt;p&gt;Let’s look at a few.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ending your test too early
&lt;/h3&gt;

&lt;p&gt;If you’re like me, you LOVE watching the numbers go up when you’re running experiments (or ads, or anything). And one of the best numbers to watch is what most A/B testing software has now. The “chance to beat” metric. This is a number that the software calculates on the fly using a multitude of variables available.&lt;/p&gt;

&lt;p&gt;This number can be misleading. If your “chance to beat” is at 100% you might be thinking, “alright, let’s end this and start the next test”, but that can get you into major trouble. This is called peeking. Peeking is when you look at the data before you’ve gathered a big enough sample size and means you haven’t hit statistical significance. Following the process of ending your tests early can lead to false positives that aren’t going to be correct in the long run.&lt;/p&gt;

&lt;p&gt;Running A/B tests takes a lot of traffic, especially as you get further into your funnel. Users drop off and you get less and less people seeing your test.&lt;/p&gt;

&lt;p&gt;Let’s look at an example. Say you have a conversion rate on a landing page of 5% and you want to get it up to 5.5%. That’s a 10% increase. Seems pretty reasonable to get there. But to be confident in that change to the landing page, you’ll need each variation to get a sample size of ~30000 visitors.&lt;/p&gt;

&lt;p&gt;I don’t know about you, but getting ~60k visitors to a landing page can be pretty tough when you are early in your startup’s lifecycle.&lt;/p&gt;

&lt;p&gt;Checkout Evan Miller’s awesome sample size calculator to better understand the audience size you need: &lt;a href="https://www.evanmiller.org/ab-testing/sample-size.html" rel="noopener noreferrer"&gt;https://www.evanmiller.org/ab-testing/sample-size.html&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Not understanding your audience
&lt;/h3&gt;

&lt;p&gt;Not all visitors to your website are the same. As marketers &amp;amp; founders, we know motivation and intent are key to marketing proficiently.&lt;/p&gt;

&lt;p&gt;A/B testing is the same. If you are running a test that needs 10000 sessions per variation and all of a sudden get 20k hits to your landing page because a blog post blew up. Is that really a good sense of what your conversion rate is going to be? Probably not. You need to make sure you understand who is visiting your site before you can make a call.&lt;/p&gt;

&lt;p&gt;Sometimes it’s worth running a test to a higher significance if you’re not confident you’re sample has a decent diversity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing all the small things
&lt;/h3&gt;

&lt;p&gt;I hope you don’t have blink 182 in your head now.&lt;/p&gt;

&lt;p&gt;I’ve talked a lot about the sample size that’s needed to run tests. In some cases it’s huge. And one of the biggest contributors to your sample size needed is the percent lift you want to see.&lt;/p&gt;

&lt;p&gt;Let’s go back to the example above of our 5% -&amp;gt; 5.5% conversion rate. Testing to significance for that example, we would need to have around 30k visitors per variation. But say we wanted to see that conversion rate lift to 6% instead by changing the whole landing page and not just the CTA copy. That drops our visitors needed per variation down to ~12k. That’s half the visitors and a much more achievable number.&lt;/p&gt;

&lt;p&gt;Making large changes to whatever you are testing is important when you you can only muster a small sample set. If you are changing something small, you won’t be hypothesizing a large lift in your test variable. But, if you make large changes to your content and go for a higher change in the test variable, your sample size needed will decrease dramatically.&lt;/p&gt;

&lt;p&gt;Don’t just go and boost your goal lift to a crazy amount here. You still need to think of testing in a scientific way and choose all of these metrics based on a good hypothesis. Otherwise you are never going to hit significance and you’ll never learn anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing is hard
&lt;/h2&gt;

&lt;p&gt;And it’s even harder at a startup. Tools like Optimizely and Google Optimize are making it easier and easier to run experiments, but they don’t give you all of the background math that needs to be done. Not knowing those statistical methods that are running in the background can lead you to false positives.&lt;/p&gt;

&lt;p&gt;Make sure you’re setting your sample size before your test and sticking to it. Don’t call a test done just because it looks like it’s going to win. Remember, data trumps gut if you have it. Watch out for traffic spikes from one spot, it can make your audience less diverse and skew your results to the max. And lastly, don’t test the small things when your throughput is low. If you’re looking to see significant results at low sample sizes, make big changes. Switch out the landing page for a completely different one, or completely change up the ad you’re running, not just a few words.&lt;/p&gt;

&lt;p&gt;Feel free to hit me up at &lt;a href="mailto:colin@manifold.co"&gt;colin@manifold.co&lt;/a&gt; if you have any questions, I love to chat about this stuff.&lt;/p&gt;

</description>
      <category>data</category>
      <category>analytics</category>
      <category>abtesting</category>
    </item>
  </channel>
</rss>
