<?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>DEV Community: Ed Stephinson</title>
    <description>The latest articles on DEV Community by Ed Stephinson (@estephinson).</description>
    <link>https://dev.to/estephinson</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%2F116722%2F8c51cb81-dd16-4ada-af4b-a906ee5cf57e.JPG</url>
      <title>DEV Community: Ed Stephinson</title>
      <link>https://dev.to/estephinson</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/estephinson"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Ed Stephinson</dc:creator>
      <pubDate>Fri, 28 Mar 2025 21:18:16 +0000</pubDate>
      <link>https://dev.to/estephinson/-5a7p</link>
      <guid>https://dev.to/estephinson/-5a7p</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/sailhouse/building-an-email-confirmation-flow-with-sailhouse-netlify-and-resend-14b8" class="crayons-story__hidden-navigation-link"&gt;Building an Email Confirmation Flow with Sailhouse, Netlify, and Resend&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;
          &lt;a class="crayons-logo crayons-logo--l" href="/sailhouse"&gt;
            &lt;img alt="Sailhouse logo" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F10597%2F119e6808-6987-4679-aff1-f629d9f2a2f8.png" class="crayons-logo__image"&gt;
          &lt;/a&gt;

          &lt;a href="/krider2010" class="crayons-avatar  crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F127714%2F00d65360-e292-4b09-8129-102d4b651e9d.jpg" alt="krider2010 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/krider2010" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Dr Claire Knight
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Dr Claire Knight
                
              
              &lt;div id="story-author-preview-content-2363699" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/krider2010" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F127714%2F00d65360-e292-4b09-8129-102d4b651e9d.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Dr Claire Knight&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

            &lt;span&gt;
              &lt;span class="crayons-story__tertiary fw-normal"&gt; for &lt;/span&gt;&lt;a href="/sailhouse" class="crayons-story__secondary fw-medium"&gt;Sailhouse&lt;/a&gt;
            &lt;/span&gt;
          &lt;/div&gt;
          &lt;a href="https://dev.to/sailhouse/building-an-email-confirmation-flow-with-sailhouse-netlify-and-resend-14b8" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 28 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/sailhouse/building-an-email-confirmation-flow-with-sailhouse-netlify-and-resend-14b8" id="article-link-2363699"&gt;
          Building an Email Confirmation Flow with Sailhouse, Netlify, and Resend
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/sailhouse/building-an-email-confirmation-flow-with-sailhouse-netlify-and-resend-14b8" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/sailhouse/building-an-email-confirmation-flow-with-sailhouse-netlify-and-resend-14b8#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Don’t block your users! Why you should adopt event-driven architecture</title>
      <dc:creator>Ed Stephinson</dc:creator>
      <pubDate>Wed, 20 Sep 2023 08:51:04 +0000</pubDate>
      <link>https://dev.to/estephinson/dont-block-your-users-why-you-should-adopt-event-driven-architecture-38e6</link>
      <guid>https://dev.to/estephinson/dont-block-your-users-why-you-should-adopt-event-driven-architecture-38e6</guid>
      <description>&lt;p&gt;Building event-driven applications offers a flexible, but markedly different approach to building applications. Let’s take a look at how an event-driven architecture can benefit your users, developers, and your application code.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does event-driven mean?
&lt;/h2&gt;

&lt;p&gt;Instead of building out complex, nested function calls to handle your application logic, you move to a world where everything is triggered by an event.&lt;/p&gt;

&lt;p&gt;Imagine a user applies for a job on your platform. Usually, this would involve a &lt;code&gt;POST&lt;/code&gt; request, with a lot of steps (e.g. parsing the resume, notifying the job poster, sending a confirmation email, storing the application details, handling internal analytics, etc) before the user receives a response. This feels slow, and could lead to frustration with the wider platform.&lt;/p&gt;

&lt;p&gt;With event-driven design, many of these steps happen in the background. The heavy lifting is done behind the scenes, making things faster for the user.&lt;/p&gt;

&lt;h2&gt;
  
  
  The benefits of event-driven applications
&lt;/h2&gt;

&lt;p&gt;Let's consider a flow every application has to deal with — user sign-ups. When a user signs up to your service, you'll want to do a few things.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create their details in the database;&lt;/li&gt;
&lt;li&gt;Send a welcome email;&lt;/li&gt;
&lt;li&gt;If they're a paid customer, activate any account features.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s take a look at the benefits an event-driven architecture lends to this flow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Built-in error handling
&lt;/h3&gt;

&lt;p&gt;With event-driven applications, errors not only become less of a problem, but also something you no longer have to fear.&lt;/p&gt;

&lt;p&gt;Taking the example of a user sign-up above, let's explore what that might look like in code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// https://api.acme.dev/users/signup&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the new user in the database&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Attempt to send a welcome email&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome.......&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Activate customer payment account&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userRecord&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;customer_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, if the email provider is down, this whole flow stops. The only way to prevent that being a problem, is by carrying on regardless whether or not the email fails to send, meaning some users may never receive that important, friendly welcome email. You might put the email send method in a try catch block, for example, to prevent the email send from blocking the next action. But that doesn’t solve the problem entirely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// https://api.acme.dev/users/signup&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;no email for you, sorry&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In an event-driven application, once the new user is safely stored in the database, you can hand the rest of the process off to your event platform (ahem, Sailhouse), and let that take care of the rest. What’s more, this means you write less application code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// https://api.acme.dev/users/signup&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the new user in the database&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Send an event to Sailhouse, where we'll take care of the rest&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;sailhouse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user-created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userRecord&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you send the event, if the &lt;code&gt;user-created&lt;/code&gt; topic doesn’t exist, Sailhouse will create it for you. When you come to create subscriptions for topics in the future (i.e. things that happen after Sailhouse processes an event), you also have the option to process historical events in the topic, so no data is lost. Sweet!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Y7yeDvDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbvvp017n9g0pgay6yy3.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Y7yeDvDt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zbvvp017n9g0pgay6yy3.jpeg" alt="A screenshot of the Sailhouse dashboard showcasing an example user-created topic, with a single send-welcome-email push subscription pointing to an API" width="800" height="486"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With our &lt;code&gt;user-created&lt;/code&gt; topic created in Sailhouse, let's focus on sending that pesky welcome email, by setting up a push &lt;code&gt;send-welcome-email&lt;/code&gt; subscription which points to a handler sending the email, which might look like the code below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// https://api.acme.dev/emails/welcome&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Welcome to ACME dev!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your email provider is down, Sailhouse will retry up to five times over the next 30 minutes and then eventually dead-letters the event (&lt;a href="https://docs.sailhouse.dev/concepts/subscriptions/#dead-letters"&gt;dead letters&lt;/a&gt; are events that are on-hold as they couldn’t be delivered as normal). You can then re-queue the event when the provider is back up again, or if you've implemented an alternative.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WhoD1iWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zs8ntg74bax3nfeahc02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WhoD1iWK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zs8ntg74bax3nfeahc02.png" alt="A screenshot of the Sailhouse dashboard showcasing the send-welcome-email subscription, showing a single successful event having been delievered" width="800" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By decoupling your application logic in this way, your customers benefit from a more reliable experience, while you have an almost self-healing application that minimises data-loss and prioritises as strong UX for your users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Faster applications for users
&lt;/h3&gt;

&lt;p&gt;Focusing again on the idea of decoupling, event-driven applications can also &lt;em&gt;really&lt;/em&gt; speed things up for your users.&lt;/p&gt;

&lt;p&gt;Using a traditional architectural approach, when a new user signs up to your product, they must wait until every action has been completed until they can start using your application. Why should they have to wait until the welcome email has been sent?&lt;/p&gt;

&lt;p&gt;When you use event-driven architecture, you massively reduce the time it takes for a user to start exploring your product after sign up. Sure, &lt;em&gt;some&lt;/em&gt; logic needs to be blocking, but now, not all of it has to be.&lt;/p&gt;

&lt;p&gt;Performance is key to a happy customer base, and this is an effective way to ensure they always have a snappy experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  Complex applications with simple code
&lt;/h3&gt;

&lt;p&gt;Complex code isn’t necessarily a bad thing. When building a product, you have to make sacrifices in order to ship fast and deliver value. This applies to both the early stages when you’re establishing product market fit, and also to a more mature product which might have thousands of successfully onboarded customers.&lt;/p&gt;

&lt;p&gt;But complex code can make it more difficult to add new features, or rework existing ones. And that’s where an event-driven architecture shines.&lt;/p&gt;

&lt;p&gt;Let’s return to our &lt;code&gt;user-created&lt;/code&gt; topic, and say you want to start checking emails in case they’re flagged for spam, and flag them internally for manual review. You can do this in Sailhouse by setting up another push subscription, and start processing events straight away.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qnU1wGVU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tg6101yrs5zhcrsz6kx4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qnU1wGVU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tg6101yrs5zhcrsz6kx4.jpeg" alt="A screenshot of the new subscription form in the Sailhouse dashboard, setting up a new spam-checking push subscription" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This extra functionality is fully isolated, with no modifications to your sign-up code, and everything can be processed in the background without disrupting the flow of your users.&lt;/p&gt;

&lt;p&gt;This is one of the huge perks of going event-driven, it makes it &lt;strong&gt;way too easy&lt;/strong&gt; to add new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sound good?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://app.sailhouse.dev"&gt;Sign up to Sailhouse&lt;/a&gt; — it’s free! (while in beta). You should also check out our growing &lt;a href="https://discord.gg/UyvsfJUE93"&gt;Discord community&lt;/a&gt;, and swing by the &lt;a href="https://github.com/orgs/sailhouse/discussions"&gt;GitHub discussions&lt;/a&gt; to talk through bugs, feature requests and all fun software things.&lt;/p&gt;

&lt;p&gt;Happy sailing!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>api</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Handle Stripe events in 2 minutes with Sailhouse</title>
      <dc:creator>Ed Stephinson</dc:creator>
      <pubDate>Wed, 30 Aug 2023 21:30:26 +0000</pubDate>
      <link>https://dev.to/estephinson/handle-stripe-events-in-2-minutes-with-sailhouse-3moo</link>
      <guid>https://dev.to/estephinson/handle-stripe-events-in-2-minutes-with-sailhouse-3moo</guid>
      <description>&lt;p&gt;Building products is hard, before you even touch the business side and start taking payments.&lt;/p&gt;

&lt;p&gt;There comes a point in every product's cycle when you need to start processing payments. Simple, right? Except what usually happens is you end up with a half-finished implementation that just about gets you by while you try to focus on shipping the product features people are paying for.&lt;/p&gt;

&lt;p&gt;Here’s where Sailhouse makes things ridiculously easy. Let’s dive into using Sailhouse to seamlessly and effortlessly handle Stripe events in a way that scales as your product does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stripe integration
&lt;/h2&gt;

&lt;p&gt;Sailhouse is a platform built on pragmatic decisions, and with that useful features. As part of our beta offering, we're building out a fully-fledged Stripe integration to make it even easier for you to get your product and payments off the ground.&lt;/p&gt;

&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%2Fsailhouse.dev%2F_astro%2Fstripe-enable.cea0e59e_Z23qxOs.webp" 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%2Fsailhouse.dev%2F_astro%2Fstripe-enable.cea0e59e_Z23qxOs.webp" alt="We see someone selecting the Stripe integration on the dashboard, choosing a topic for the events to be sent to, and then enabling it"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building a webhook to receive Stripe events itself is pretty straightforward, but the proper distribution — while maintaining verification — is a job for an events platform. Here’s where Sailhouse comes in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Enabling the integration
&lt;/h3&gt;

&lt;p&gt;Log in to your Sailhouse account and head over to your dashboard.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a topic to receive your events, for example, &lt;code&gt;stripe-events&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Enable the Stripe integration by navigating to Apps &amp;gt; &lt;code&gt;your-app&lt;/code&gt; &amp;gt; Integrations, and select your new &lt;code&gt;stripe-events&lt;/code&gt; topic&lt;/li&gt;
&lt;li&gt;Copy the endpoint provided, navigate to Stripe, and create a new Webhook, selecting all available events&lt;/li&gt;
&lt;li&gt;Take the secret from Stripe, and save it in the Sailhouse integration settings to activate the endpoint&lt;/li&gt;
&lt;/ul&gt;

&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%2Fsailhouse.dev%2F_astro%2Fstripe-configure.96e2965b_kbhCI.webp" 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%2Fsailhouse.dev%2F_astro%2Fstripe-configure.96e2965b_kbhCI.webp" alt="There is a split browser screen, of the Sailhouse and Stripe dashboards. The user takes the dedicated webhook endpoint for the just-enabled Stripe integration, and configures the webhook on Stripe. The user selects all available events, then copies the webhook signature from Stripe into the integration configuration on Sailhouse, which finalises the setup."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, every single event on Stripe is sent to and handled on Sailhouse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wait a minute, that's noisy, surely?
&lt;/h3&gt;

&lt;p&gt;Ah-ha! You fell into our pricing trap. (Just kidding, the beta is currently free to use under our fair use policy 😉.)&lt;/p&gt;

&lt;p&gt;But if you’d like to reduce the amount of events received — or drill down into what’s most important, Sailhouse has got you covered with &lt;a href="https://docs.sailhouse.dev/concepts/subscriptions/#subscription-filters" rel="noopener noreferrer"&gt;Subscription Filters&lt;/a&gt;.&lt;/p&gt;

&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%2Fsailhouse.dev%2F_astro%2Fsub-filter.e07ac78e_2lzrIF.webp" 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%2Fsailhouse.dev%2F_astro%2Fsub-filter.e07ac78e_2lzrIF.webp" alt="Subscription filter for stripe events"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Instead of building custom logic to handle Stripe events, verify webhooks, and distribute that information in your code, you can add a subscription filter on your Stripe events — as with any other event on Sailhouse.&lt;/p&gt;

&lt;p&gt;For example, you can create an &lt;code&gt;invoice-paid&lt;/code&gt; subscription, which filters on Stripe event &lt;code&gt;type&lt;/code&gt; for &lt;code&gt;invoice.paid&lt;/code&gt;. You can also set up Slack notifications for any &lt;code&gt;invoice.payment_failed&lt;/code&gt; events thanks to the Sailhouse Slack integration!&lt;/p&gt;

&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%2Fsailhouse.dev%2F_astro%2Fstripe-slack-integration.92ca4e09_wlxGz.webp" 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%2Fsailhouse.dev%2F_astro%2Fstripe-slack-integration.92ca4e09_wlxGz.webp" alt="Slack recieving a Stripe Event"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Handling Stripe events
&lt;/h2&gt;

&lt;p&gt;You can handle your Stripe events in Sailhouse just like any other event. Here are some examples.&lt;/p&gt;

&lt;p&gt;You could configure a push subscription:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;subscriptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invoice-paid&lt;/span&gt;
    &lt;span class="na"&gt;topic&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stripe-events&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;push&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://acme-inc.com/api/invoice-paid&lt;/span&gt;
    &lt;span class="na"&gt;filter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;invoice.paid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or handle the event in your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getEvents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stripe-events&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;customer-created&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Do useful thing&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ack&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;h2&gt;
  
  
  Let us know what you’re building!
&lt;/h2&gt;

&lt;p&gt;This is just the start of a whole suite of awesome integrations, and we can't wait to see what you make with them.&lt;/p&gt;

&lt;p&gt;Come show off what you're building &lt;a href="https://discord.gg/UyvsfJUE93" rel="noopener noreferrer"&gt;in the official Sailhouse Discord&lt;/a&gt;, or &lt;a href="https://twitter.com/sailhousedev" rel="noopener noreferrer"&gt;tag us on Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy Sailing!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>serverless</category>
      <category>api</category>
    </item>
    <item>
      <title>Introducing Sailhouse, the easiest way to send events ⛵️</title>
      <dc:creator>Ed Stephinson</dc:creator>
      <pubDate>Thu, 24 Aug 2023 21:42:11 +0000</pubDate>
      <link>https://dev.to/estephinson/introducing-sailhouse-the-easiest-way-to-send-events-2ok7</link>
      <guid>https://dev.to/estephinson/introducing-sailhouse-the-easiest-way-to-send-events-2ok7</guid>
      <description>&lt;p&gt;Yes it's out, yes people are using it, but now it's time for it to say hello! 👋&lt;/p&gt;

&lt;p&gt;Introducing, &lt;strong&gt;Sailhouse&lt;/strong&gt; ⛵️!&lt;/p&gt;

&lt;h2&gt;
  
  
  Our mission and objectives
&lt;/h2&gt;

&lt;p&gt;Sailhouse is pub sub on easy mode. No infra, no clusters, no regions, no sizing. Just events, topics and subscriptions.&lt;/p&gt;

&lt;p&gt;Event-driven applications are a proven winner, Sailhouse is about making it as simple as possible to build them. With an intuitive CLI, powerful dashboard and slick integrations — you focus on building apps, we handle the plumbing.&lt;/p&gt;

&lt;p&gt;It's all quite simple really — making complex, reliable, and performant applications as easy to build as possible.&lt;/p&gt;

&lt;p&gt;Yes yes, big dreams, whatever.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Sailhouse team
&lt;/h2&gt;

&lt;p&gt;Sailhouse is being built by people with experience, and passion, for developer tooling. With experience at industry/category-defining developer-focused companies such as &lt;a href="https://netlify.com/"&gt;Netlify&lt;/a&gt;, we know how to build a strong offering.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/ejsdev"&gt;Ed Stephinson&lt;/a&gt;, founder, tech lead of composable tooling at Netlify&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://whitep4nth3r.com/"&gt;Salma Alam-Naylor&lt;/a&gt;, advisor, former DX at Netlify, soon to be somewhere exciting 👀&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where are we now?
&lt;/h2&gt;

&lt;p&gt;It’s a feature packed launch, but we’re in a great place to innovate.&lt;/p&gt;

&lt;p&gt;You can use the CLI or dashboard to manage your whole events system. From creating topics in a flash with &lt;code&gt;sailhouse topics create&lt;/code&gt; or managing the Stripe integration from the dashboard, it’s tooling focused on usecases, not implementation detail.&lt;/p&gt;

&lt;p&gt;We’re focusing on our free-to-use beta. This is capped at 200 events a month (soft limit, with increasingly snarky emails the more you go over), while we fine tune what we’ve got.&lt;/p&gt;

&lt;p&gt;It can handle scale too, there was one 24 hour period processing over 40,000 events without us even noticing.&lt;/p&gt;

&lt;p&gt;We’ve got native SDKs for both Go and TypeScript (plus JavaScript, fear not), with more on the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s in store for the next 12 months
&lt;/h2&gt;

&lt;p&gt;At a high level, here are our objectives for the next 12 months.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rollout Sailhouse from Beta -&amp;gt; Stable&lt;/li&gt;
&lt;li&gt;Build useful features, grounded in real-world uses

&lt;ul&gt;
&lt;li&gt;Integrations are a key part of this&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Introduce more SDKs&lt;/li&gt;
&lt;li&gt;Focus on stability and performance&lt;/li&gt;
&lt;li&gt;Rollout to more edge locations&lt;/li&gt;
&lt;li&gt;Most importantly, build a rich, diverse and engaged community&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Is Sailhouse Open Source?
&lt;/h2&gt;

&lt;p&gt;Yes, kinda.&lt;/p&gt;

&lt;p&gt;It's probable the core will always remain closed. That's both a business and practical decision. However, much like how &lt;a href="https://sentry.io/"&gt;Sentry&lt;/a&gt; have some of their &lt;a href="https://github.com/getsentry/relay"&gt;services&lt;/a&gt; open-source, we may follow that route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Go get started, like now, go!
&lt;/h2&gt;

&lt;p&gt;Our &lt;a href="https://github.com/sailhouse/docs"&gt;docs are open source&lt;/a&gt;! If you'd like to contribute, PRs and issues are actively welcomed. We're also &lt;a href="https://discord.gg/UyvsfJUE93"&gt;building a community on discord&lt;/a&gt; for more real-time interaction. Otherwise, our trusty &lt;a href="https://github.com/orgs/sailhouse/discussions"&gt;GitHub Discussions&lt;/a&gt; board is the place to raise feature requests and more.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>go</category>
      <category>api</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
