<?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: François Farge</title>
    <description>The latest articles on DEV Community by François Farge (@fargito).</description>
    <link>https://dev.to/fargito</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%2F862015%2Ffeafa56d-9f33-42b1-a87a-0a898eadecb4.png</url>
      <title>DEV Community: François Farge</title>
      <link>https://dev.to/fargito</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fargito"/>
    <language>en</language>
    <item>
      <title>Easy Integration Tests for Event-Driven AWS Architectures with EventScout 📨🔭</title>
      <dc:creator>François Farge</dc:creator>
      <pubDate>Thu, 16 Feb 2023 11:26:37 +0000</pubDate>
      <link>https://dev.to/slsbytheodo/easy-integration-tests-for-event-driven-aws-architectures-with-eventscout-5d05</link>
      <guid>https://dev.to/slsbytheodo/easy-integration-tests-for-event-driven-aws-architectures-with-eventscout-5d05</guid>
      <description>&lt;p&gt;When building event-driven Serverless applications on AWS, EventBridge is a must-have. It's simple to use, scalable and inexpensive.&lt;/p&gt;

&lt;p&gt;However, a challenge I often faced on event-driven projects was testing. I could not find an easy way to validate that the events sent by my application were matching my expectations. The critical challenge was to list events sent through an event bus, which is not natively possible with EventBridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I made a cool EventBridge integration testing library for Typescript, &lt;a href="https://github.com/fargito/event-scout" rel="noopener noreferrer"&gt;check it out&lt;/a&gt;!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What could go wrong in my event-driven architecture?&lt;/li&gt;
&lt;li&gt;Events? What events&lt;/li&gt;
&lt;li&gt;Searching for and EventBridge testing tool&lt;/li&gt;
&lt;li&gt;
Building a scalable EventBridge testing infrastructure

&lt;ul&gt;
&lt;li&gt;Simple to use&lt;/li&gt;
&lt;li&gt;Scalable&lt;/li&gt;
&lt;li&gt;Cheap&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Use EventScout in your infrastructure

&lt;ul&gt;
&lt;li&gt;Deploy resources with EventScout&lt;/li&gt;
&lt;li&gt;Use the EventScout client in your tests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What could go wrong in my event-driven architecture?
&lt;/h2&gt;

&lt;p&gt;Since its initial release in 2019, EventBridge has been widely used to build event-driven Architecture on AWS, progressively replacing older tools such as SQS and SNS (although these still have valid specific use cases).&lt;/p&gt;

&lt;p&gt;I have always been a fan of EventBridge. It’s simple to use, powerful and inexpensive. However, during my first projects with EventBridge, I found it very difficult to test my asynchronous applications.&lt;/p&gt;

&lt;p&gt;For example, let’s imagine a very simple application with EventBridge:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Fqsfg8ln8kmw8x3ssugj4.png" class="article-body-image-wrapper"&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%2Farticles%2Fqsfg8ln8kmw8x3ssugj4.png" alt="Simple Asynchronous Architecture" width="800" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this architecture, we have two Lambdas. The first one is synchronously triggered by ApiGateway. It then puts an &lt;em&gt;ORDER_CREATED&lt;/em&gt; event into EventBridge. That event triggers the execution of a second Lambda. Pretty simple, right?&lt;/p&gt;

&lt;p&gt;However, many things could go wrong in our system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;our &lt;strong&gt;application&lt;/strong&gt; code can behave unexpectedly and fail to send the event&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Ft7gxugo64p23p9jdcfsm.png" class="article-body-image-wrapper"&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%2Farticles%2Ft7gxugo64p23p9jdcfsm.png" alt="Application issue" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;there can be &lt;strong&gt;configuration&lt;/strong&gt; issues:

&lt;ul&gt;
&lt;li&gt;invalid IAM permissions&lt;/li&gt;
&lt;li&gt;missing environment variables&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onOrderCreated&lt;/code&gt; could listen to the wrong event&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2F81co6hq35bwtwvckn1rf.png" class="article-body-image-wrapper"&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%2Farticles%2F81co6hq35bwtwvckn1rf.png" alt="Configuration issues" width="800" height="137"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To alleviate these risks, we can test our system at 3 different levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;unit tests&lt;/strong&gt;: they can address the &lt;strong&gt;application&lt;/strong&gt; failure cause. They validate that the code behaves as expected, and mock its external interactions. Efficient unit testing for Lambda is a complex topic in itself, that I will address in another article about hexagonal architecture for Serverless&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;integration tests&lt;/strong&gt;: they assert that several components in our system behave as expected together. There are multiple types of integration tests, and in particular &lt;a href="https://dev.to/kumo/stop-using-a-local-environment-to-develop-serverless-applications-43a3"&gt;cloud-native integration tests&lt;/a&gt;. Fortunately for us, these tests can prevent our &lt;strong&gt;configuration&lt;/strong&gt; failure cause&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;end-to-end tests&lt;/strong&gt;: they consider our whole system as a black box and only interact with its interfaces. They are beyond the scope of this article&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the rest of this article, we will focus on &lt;strong&gt;integration tests&lt;/strong&gt; and &lt;strong&gt;EventBridge&lt;/strong&gt;. In our system, two integration tests would seem relevant.&lt;/p&gt;

&lt;p&gt;The simplest one tests the interactions between EventBridge and &lt;code&gt;onOrderCreated&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2F7686umx8j89dk8f4il8y.png" class="article-body-image-wrapper"&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%2Farticles%2F7686umx8j89dk8f4il8y.png" alt="First integration test" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In order to validate that EventBridge and &lt;code&gt;onOrderCreated&lt;/code&gt; are correctly configured, we can simply put a valid event in EventBridge at the beginning of our test, then wait and check that our Lambda has been invoked, by checking CloudWatch logs for example.&lt;/p&gt;

&lt;p&gt;The second integration test is more complex and aims to check the interactions between the resources at the start of our process.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2F17mgh7j9fxv5vh4pviyl.png" class="article-body-image-wrapper"&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%2Farticles%2F17mgh7j9fxv5vh4pviyl.png" alt="Second integration test" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the goal of our test is to call the endpoint provided by API Gateway and assert that the &lt;code&gt;createOrder&lt;/code&gt; Lambda has sent an event matching our expectations in EventBridge. And this is where it gets truly complicated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Events? What events?
&lt;/h2&gt;

&lt;p&gt;Testing event-driven architectures is a whole topic in itself, but in particular, EventBridge doesn’t make it easier.&lt;/p&gt;

&lt;p&gt;But what makes EventBridge-powered applications so difficult to test? EventBridge provides no way of listing events it has received, or check that an event has been put to it. While these features would make little sense in a production environment, they would have been much helpful to check that our code has produced some events.&lt;/p&gt;

&lt;p&gt;In order to assert that events have transited through a bus, we need to project them somehow in an observable place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Searching for an EventBridge testing tool
&lt;/h2&gt;

&lt;p&gt;In order to bypass EventBridge's limitations on the testing topic, I searched for an existing tool.&lt;/p&gt;

&lt;p&gt;But what would I want from this tool?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I’d want it to be &lt;strong&gt;simple&lt;/strong&gt; to set up. Developers need to encounter the least possible friction to write good integration tests&lt;/li&gt;
&lt;li&gt;I’d want it to be &lt;strong&gt;scalable&lt;/strong&gt;: I need my integration tests to be able to run in parallel without interference&lt;/li&gt;
&lt;li&gt;I’d want it to remain &lt;strong&gt;cheap&lt;/strong&gt;: my whole architecture uses the serverless pay-as-you-go pricing model, and my tests must remain inexpensive enough&lt;/li&gt;
&lt;li&gt;Obviously, it needs to be &lt;strong&gt;secure&lt;/strong&gt; (do I need to explain why?)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In found several solutions online:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up &lt;a href="https://aws.amazon.com/blogs/compute/testing-amazon-eventbridge-events-using-aws-step-functions/" rel="noopener noreferrer"&gt;a Step Function&lt;/a&gt; for each test&lt;/li&gt;
&lt;li&gt;Creating an EventBridge target to dump events to SQS. This approach was proposed in several articles (&lt;a href="https://medium.com/serverless-transformation/bridge-integrity-integration-testing-strategy-for-eventbridge-based-serverless-architectures-b73529397251" rel="noopener noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://serverlessfirst.com/eventbridge-testing-guide/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) and implemented in the &lt;a href="https://github.com/aleios-cloud/sls-test-tools" rel="noopener noreferrer"&gt;sls-test-tools&lt;/a&gt; library&lt;/li&gt;
&lt;li&gt;Using CloudWatch to dump and debug events, &lt;a href="https://www.boyney.io/blog/2021-04-15-debug-eventbridge-events-with-cloudwatch" rel="noopener noreferrer"&gt;introduced by David Boyne&lt;/a&gt;. Although it was not directly aimed at testing, maybe this solution could be used for integration tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted to evaluate the perks and drawbacks of each solution, so I scored them against my constraints and put them in a comparative table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Simple setup&lt;/th&gt;
&lt;th&gt;Scalable&lt;/th&gt;
&lt;th&gt;Cheap&lt;/th&gt;
&lt;th&gt;Secure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Step functions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Manual setup required&lt;/td&gt;
&lt;td&gt;⚠️ Probably one infrastructure per test&lt;/td&gt;
&lt;td&gt;✅ Pay-as-you-go&lt;/td&gt;
&lt;td&gt;✅ IAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SQS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ NPM package &lt;br&gt;✅ Automated resources creation&lt;/td&gt;
&lt;td&gt;❌ No parallelism: SQS can only have one consumer &lt;br&gt;⚠️ &lt;a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html" rel="noopener noreferrer"&gt;SQS creation limits&lt;/a&gt;
&lt;/td&gt;
&lt;td&gt;✅ Pay-as-you-go&lt;br&gt;⚠️ No automatic disabling of resources&lt;/td&gt;
&lt;td&gt;✅ IAM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CloudWatch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;❌ Manual setup required&lt;/td&gt;
&lt;td&gt;✅ Unlimited parallel reads&lt;/td&gt;
&lt;td&gt;❌ CloudWatch logs are expensive!&lt;br&gt;❌ No automatic rule disabling&lt;/td&gt;
&lt;td&gt;✅ IAM&lt;br&gt;⚠️ Sensible event data may persist in the logs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Although all of these solutions inspired me and made me realize that testing EventBridge was possible, none of them completely fulfilled my requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a scalable EventBridge testing infrastructure
&lt;/h2&gt;

&lt;p&gt;I therefore decided to build and open-source an EventBridge integration tests library. This is why I am very proud to introduce &lt;strong&gt;EventScout&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;It is designed following the requirements I had applied to existing online solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple to use
&lt;/h3&gt;

&lt;p&gt;EventScout is composed of two highly reusable parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A CDK construct to deploy the necessary resources&lt;/li&gt;
&lt;li&gt;A lightweight client to use in the tests, for example with Jest of Vitest&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Fidhhc7dl16fxwf660q56.png" class="article-body-image-wrapper"&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%2Farticles%2Fidhhc7dl16fxwf660q56.png" alt="Event-Scout high-level design" width="800" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you wish to learn how to use EventScout on you project, head to &lt;a href="https://github.com/fargito/event-scout" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Scalable&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Making our testing infrastructure scalable requires that our tests can be run in parallel. For this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We must not be constrained by AWS quotas (e.g. after an SQS queue is deleted, another with the same name &lt;a href="https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_DeleteQueue.html" rel="noopener noreferrer"&gt;cannot be created for 60 seconds&lt;/a&gt;). Therefore EventScout ensures only the minimal resources are created &lt;strong&gt;during&lt;/strong&gt; a test suite, and reuse resources between tests&lt;/li&gt;
&lt;li&gt;We must be able to receive events independently for each test suite:

&lt;ul&gt;
&lt;li&gt;Each test suite declares a pattern of events to watch (a &lt;strong&gt;trail&lt;/strong&gt; of events)&lt;/li&gt;
&lt;li&gt;Each trail is then completely independent from all other trails to allow parallel query. Each trail can be queried as many times as necessary&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Therefore, a test suite’s sequence diagram looks like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Fj1xjc9rtea0qch0stqho.png" class="article-body-image-wrapper"&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%2Farticles%2Fj1xjc9rtea0qch0stqho.png" alt="Sequence diagram" width="800" height="525"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From an architectural point of view, let’s dive in this sequence:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Farticles%2Fr54w3fjtvjxdoygzupit.png" class="article-body-image-wrapper"&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%2Farticles%2Fr54w3fjtvjxdoygzupit.png" alt="Architecture sequence" width="724" height="952"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;During its setup phase, the test creates an &lt;strong&gt;EventBridge&lt;/strong&gt; rule with the desired pattern, linking to EventScout’s ingestion lambda (&lt;code&gt;storeEvents&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;The test produces some events that match the pattern&lt;/li&gt;
&lt;li&gt;The newly created rule is called&lt;/li&gt;
&lt;li&gt;The rule triggers the ingestion lambda&lt;/li&gt;
&lt;li&gt;Using metadata information from the rule, &lt;code&gt;storeEvents&lt;/code&gt; saves the event in the correct trail.&lt;/li&gt;
&lt;li&gt;The test can query the trail and perform assertions&lt;/li&gt;
&lt;li&gt;A the end of the test, the only thing left is to delete the EventBridge rule&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two features are key here to make EventScout scalable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using one EventBridge rule per test suite:

&lt;ul&gt;
&lt;li&gt;it makes each test fully independent from all others&lt;/li&gt;
&lt;li&gt;it reuses infrastructure and only needs to create and delete the rule, which is quite fast&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Using the rule metadata to store events in a trail:

&lt;ul&gt;
&lt;li&gt;there is no need for additional request or computation to know which test suites are interested in the received event&lt;/li&gt;
&lt;li&gt;if an event matching two rules is sent, it will be stored in two trails, which enables parallel tests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cheap
&lt;/h3&gt;

&lt;p&gt;EventScout only uses serverless resources (Lambda, DynamoDB, API Gateway) to take full advantage of the pay-as-you-go model. Moreover, EventScout ensures that no unnecessary resources are used through &lt;strong&gt;automatic trail cleanup&lt;/strong&gt;. Leveraging DynamoDB’s time-to-live capabilities, it automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cleans recorded trail events after 15 minutes&lt;/li&gt;
&lt;li&gt;stops the event rules after 15 minutes to handle the case when they haven’t been manually stopped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes EventScout the safest way to run integration tests without worrying about their cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All interactions between the EventScout client and the construct are secured by IAM&lt;/li&gt;
&lt;li&gt;Events are automatically cleaned after 15 minutes, removing any privacy issue&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use EventScout on your infrastructure
&lt;/h2&gt;

&lt;p&gt;Leveraging EventScout capabilities on your infrastructure is pretty straightforward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy resources with EventScout construct
&lt;/h3&gt;

&lt;p&gt;Start by installing the EventScout construct:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @event-scout/construct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, instantiate the CDK construct in your CDK app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EventScout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@event-scout/construct&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CfnOutput&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EventBus&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-cdk-lib/aws-events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// create the necessary resources&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;restEndpoint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EventScout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EventScout&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="na"&gt;eventBus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;EventBus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEventBusName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EventBus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventBusName&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// export the endpoint value for easier use in tests&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CfnOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EventScoutEndpoint&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;restEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EventScout endpoint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;exportName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;your export name&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The export here is not required, but will be useful to retrieve the EventScout endpoint for your tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use the EventScout client in your tests
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @event-scout/client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can head to &lt;a href="https://github.com/fargito/event-scout/blob/main/packages/client/README.md" rel="noopener noreferrer"&gt;the documentation&lt;/a&gt; for details on how to instantiate and use the client in your tests.&lt;/p&gt;

&lt;p&gt;Congratulations, you have unlocked the power of EventScout! Use it wisely...&lt;/p&gt;

</description>
      <category>eventbridge</category>
      <category>integration</category>
      <category>tests</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Introducing Swarmion 🐝, a Type-safe Serverless Microservices Framework</title>
      <dc:creator>François Farge</dc:creator>
      <pubDate>Thu, 19 May 2022 12:23:00 +0000</pubDate>
      <link>https://dev.to/slsbytheodo/introducing-swarmion-a-type-safe-serverless-microservices-framework-3fmp</link>
      <guid>https://dev.to/slsbytheodo/introducing-swarmion-a-type-safe-serverless-microservices-framework-3fmp</guid>
      <description>&lt;p&gt;The serverless computing paradigm introduced a lot of opportunities to create more scalable and cost-efficient software, but it also came with its own challenges, some of which we harshly experienced.&lt;/p&gt;

&lt;p&gt;After more than two years spent building multiple real-world applications, ranging from small startups to large groups, we decided to share our learnings and help other teams build awesome products.&lt;/p&gt;

&lt;p&gt;This is why we would like to introduce &lt;strong&gt;Swarmion&lt;/strong&gt;, an open-source framework, dedicated to Serverless microservices. A great emphasis has been done on developer experience, since working with a Typescript monorepo is a challenge.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Swarmion? 🐝
&lt;/h2&gt;

&lt;p&gt;Swarmion is an open-source framework for building type-safe Serverless microservices at scale. It takes full advantage of the &lt;strong&gt;Serverless Framework&lt;/strong&gt; to handle provisioning and deployment of resources, while adding support for microservices and end-to-end type-safety.&lt;/p&gt;

&lt;p&gt;It is composed of two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;template&lt;/strong&gt; for starting state-of-the-art projects&lt;/li&gt;
&lt;li&gt;a set of &lt;strong&gt;tools and plugins&lt;/strong&gt;, to ease the communication between microservices and secure their deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Today, we are going to focus on the first part, stay tuned for more articles...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL:DR: try it out&lt;/strong&gt;! Head to the end of this article for a quick tutorial!&lt;/p&gt;

&lt;h1&gt;
  
  
  Our core beliefs
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Your codebase should adapt to your team organization
&lt;/h3&gt;

&lt;p&gt;Changes in the way you organize your teams should not have an impact on the speed at which you can develop and deploy new features. Therefore, Swarmion uses a flexible microservices approach in a monorepo.&lt;/p&gt;

&lt;h3&gt;
  
  
  DRY (Don't Repeat Yourself)
&lt;/h3&gt;

&lt;p&gt;Having several teams working in the same environment requires efficient collaboration. Swarmion allows to clearly separate the shared logic and interfaces from the service-specific logic for better decoupling.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer experience is key for code quality
&lt;/h3&gt;

&lt;p&gt;As your codebase grows, testing and deployment times are likely to skyrocket. Swarmion uses optimized low-level software (esbuild, vitejs) to reduce testing and building times and a smart monorepo management tool (&lt;a href="https://nx.dev/" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;) to provide a top-level developer experience and reduce CI/CD delays.&lt;/p&gt;

&lt;h1&gt;
  
  
  ✨ Template features
&lt;/h1&gt;

&lt;p&gt;The template comes with state of the art tooling for a Typescript monorepo. The main philosophy is to allow easy customization of the different tools used in the packages, without having to write too many code; every tool can be configured at the root level and extended through composition at the package level.&lt;/p&gt;

&lt;h3&gt;
  
  
  Yarn 3 with workspaces
&lt;/h3&gt;

&lt;p&gt;Yarn 3 and workspaces allows to create a monorepo with multiple packages, each with their own dependencies. Every package in the monorepo is considered as an npm package inside the monorepo. Every modification to its source code is instantly available to the other packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Nx
&lt;/h3&gt;

&lt;p&gt;A powerful and extensible build system, &lt;a href="https://nx.dev" rel="noopener noreferrer"&gt;Nx&lt;/a&gt;, is used to manage dependencies between packages, provide visualization of the monorepo dependencies through the &lt;a href="https://nx.dev/cli/dep-graph" rel="noopener noreferrer"&gt;&lt;code&gt;yarn nx graph&lt;/code&gt; command&lt;/a&gt; and gain access to powerful custom generators. Our &lt;a href="https://www.swarmion.dev/docs/code-structure/nx-plugin" rel="noopener noreferrer"&gt;nx plugin&lt;/a&gt; already has two generators, for libraries and serverless services (more are coming).&lt;/p&gt;

&lt;p&gt;Nx also avoids unnecessary computation when running commands inside the monorepo, using local caching and changes detection for an smooth developer experience and an optimized CI/CD.&lt;/p&gt;

&lt;h3&gt;
  
  
  Typescript
&lt;/h3&gt;

&lt;p&gt;Since every package inside the monorepo is using Typescript, every line of code can be statically checked. A strict and strong Typescript configuration is located at the root level, extended throughout the packages using composition.&lt;/p&gt;

&lt;h3&gt;
  
  
  ESLint
&lt;/h3&gt;

&lt;p&gt;A comprehensive set of formatting (through &lt;a href="https://github.com/prettier/eslint-plugin-prettier" rel="noopener noreferrer"&gt;&lt;code&gt;eslint-plugin-prettier&lt;/code&gt;&lt;/a&gt;) and linting rules, generated with &lt;a href="https://github.com/theodo/clinter" rel="noopener noreferrer"&gt;Clinter&lt;/a&gt;. Once again, each package can easily extend the root configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared Typescript libraries
&lt;/h3&gt;

&lt;p&gt;One of the main challenges of a Typescript monorepo is to build shared Typescript libraries. Packages are transpiled in &lt;code&gt;cjs&lt;/code&gt;, &lt;code&gt;esm&lt;/code&gt; (thanks to &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt;) and &lt;code&gt;.d.ts&lt;/code&gt; Typescript declaration file, to enable any usage across the monorepo.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jest
&lt;/h3&gt;

&lt;p&gt;Every package has testing configured through &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;&lt;code&gt;jest&lt;/code&gt;&lt;/a&gt;, with a default configuration that can easily be extended, thanks to the &lt;code&gt;jest.config.ts&lt;/code&gt; file at the package level.&lt;/p&gt;

&lt;h3&gt;
  
  
  VS Code support
&lt;/h3&gt;

&lt;p&gt;Each package in the monorepo is defined as a workspace in the multi-root workspaces. It enables easier browsing and searching features, bringing the same navigation than in a standard codebase.&lt;/p&gt;

&lt;p&gt;Using multi-root workspaces makes it possible to use the great &lt;a href="https://github.com/jest-community/vscode-jest#how-to-use-the-extension-with-monorepo-projects" rel="noopener noreferrer"&gt;&lt;code&gt;vs-code&lt;/code&gt; extension&lt;/a&gt;, which makes it possible to run and debug tests directly inside VS Code.&lt;/p&gt;

&lt;h1&gt;
  
  
  🛠 Generate a project with Swarmion
&lt;/h1&gt;

&lt;p&gt;To create a Swarmion project, head to &lt;a href="https://www.github.com/swarmion/template" rel="noopener noreferrer"&gt;https://github.com/swarmion/template&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Click the "use this template" button&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%2Fraw.githubusercontent.com%2Ffargito%2Fdevto-articles%2Fmaster%2Fblog-posts%2F1-announcing-swarmion%2Fstatic%2Fuse_this_template_button.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%2Fraw.githubusercontent.com%2Ffargito%2Fdevto-articles%2Fmaster%2Fblog-posts%2F1-announcing-swarmion%2Fstatic%2Fuse_this_template_button.png" alt="Use this template button"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you're all set! Follow the &lt;a href="https://www.swarmion.dev/docs/getting-started/installation" rel="noopener noreferrer"&gt;install docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick overview
&lt;/h2&gt;

&lt;p&gt;The generated repo will have the following structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;├── backend/
|   ├── core/                       # core service
|   ├── users/                      # users service
|   └── ...                         # other deployed services
|
├── frontend/
|   ├── app/
|   ├── cloudfront/
|   └── ...                         # other deployed services
|
├── commonConfiguration/            # configuration files such as jest, babel...
|   ├── babel.config.js
|   └── lintstaged-base-config.js
|
├── contracts/                      # JSONSchema-based binding contracts
|   ├── core-contracts/
|   ├── users-contracts/
|   └── ...                         # other contracts, used between deployed services
|
├── packages/
|   ├── configuration/              # common constants used in all services
|   ├── serverless-configuration/   # common constants used in all serverless deployed services
|   ├── serverless-helpers/         # a set of shared helpers
|   └── ...                         # other internal shared packages
|
├── package.json                   # shared dependencies and global scripts
└── yarn.lock                      # unique lock file, using yarn workspaces

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To learn more about this structure, head to the &lt;a href="https://www.swarmion.dev/docs/code-structure/monorepo" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;!&lt;/p&gt;

&lt;h1&gt;
  
  
  🎁 Wrapping up
&lt;/h1&gt;

&lt;p&gt;Be sure to check out &lt;a href="https://www.swarmion.dev/" rel="noopener noreferrer"&gt;https://www.swarmion.dev/&lt;/a&gt; for docs about Swarmion, the &lt;a href="https://github.com/swarmion/template" rel="noopener noreferrer"&gt;template repo&lt;/a&gt; and the &lt;a href="https://github.com/swarmion/swarmion" rel="noopener noreferrer"&gt;tools repo&lt;/a&gt;. Any feedback is welcome!&lt;/p&gt;

&lt;h3&gt;
  
  
  🎄 Upcoming features
&lt;/h3&gt;

&lt;p&gt;Swarmion is being maintained by a core team of several people, we are striving to deliver more and more features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;create-swarmion-app&lt;/code&gt; script to create an app even more easily&lt;/li&gt;
&lt;li&gt;more contracts in &lt;a href="https://www.npmjs.com/package/@swarmion/serverless-contracts" rel="noopener noreferrer"&gt;our library&lt;/a&gt; to define type-safe and runtime interactions between services&lt;/li&gt;
&lt;li&gt;frontend generators for apps and libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🤝 Acknowledgments
&lt;/h3&gt;

&lt;p&gt;Swarmion was created by Adrien Cacciaguerra and François Farge.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/adriencaccia" rel="noopener noreferrer"&gt;@adriencaccia&lt;/a&gt; - &lt;a href="https://github.com/adriencaccia" rel="noopener noreferrer"&gt;adriencaccia&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://twitter.com/farge_francois" rel="noopener noreferrer"&gt;@farge_francois&lt;/a&gt; - &lt;a href="https://github.com/fargito" rel="noopener noreferrer"&gt;fargito&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks to the swarmion team: &lt;a href="https://github.com/guillaumeduboc" rel="noopener noreferrer"&gt;Guillaume Duboc&lt;/a&gt;, &lt;a href="https://github.com/MaximeVivier" rel="noopener noreferrer"&gt;Maxime Vivier&lt;/a&gt;, &lt;a href="https://github.com/Sc0ra" rel="noopener noreferrer"&gt;Axel Fournier&lt;/a&gt; and &lt;a href="https://github.com/StanHannebelle" rel="noopener noreferrer"&gt;Stanislas Hannebelle&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to all the contributors!&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://www.theodo.fr/" rel="noopener noreferrer"&gt;Theodo&lt;/a&gt; for sponsoring this project!&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>typescript</category>
      <category>monorepo</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
