<?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: Stephen Sennett</title>
    <description>The latest articles on DEV Community by Stephen Sennett (@ssennettau).</description>
    <link>https://dev.to/ssennettau</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%2F645925%2F6bd00b25-bc29-4890-9604-53068c2577c9.jpg</url>
      <title>DEV Community: Stephen Sennett</title>
      <link>https://dev.to/ssennettau</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ssennettau"/>
    <language>en</language>
    <item>
      <title>Does Scale-to-Zero Redefine Aurora’s ‘Serverlessness’?</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Sun, 24 Nov 2024 15:29:29 +0000</pubDate>
      <link>https://dev.to/aws-heroes/does-scale-to-zero-redefine-auroras-serverlessness-5hf7</link>
      <guid>https://dev.to/aws-heroes/does-scale-to-zero-redefine-auroras-serverlessness-5hf7</guid>
      <description>&lt;p&gt;Amazon Aurora Serverless v2 now supports &lt;a href="https://aws.amazon.com/blogs/database/introducing-scaling-to-0-capacity-with-amazon-aurora-serverless-v2/" rel="noopener noreferrer"&gt;&lt;strong&gt;scale-to-zero&lt;/strong&gt;&lt;/a&gt;, allowing you to stop paying for your database when it isn't in use. &lt;/p&gt;

&lt;p&gt;Sounds great - but what does it mean, and is it &lt;em&gt;really serverless&lt;/em&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%2Fub9qw5ngpeygpswjz1kl.jpg" 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%2Fub9qw5ngpeygpswjz1kl.jpg" alt="Is it really serverless?" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🖥️ What is Aurora Serverless v2?
&lt;/h2&gt;

&lt;p&gt;First, some basics: &lt;a href="https://aws.amazon.com/rds/aurora/serverless/" rel="noopener noreferrer"&gt;Aurora Serverless v2&lt;/a&gt; abstracts away the management of individual underlying database instances, and replaces it with "&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html#aurora-serverless-v2.how-it-works.capacity" rel="noopener noreferrer"&gt;Aurora Capacity Units&lt;/a&gt;" (ACU's).&lt;/p&gt;

&lt;p&gt;Each ACU is equivalent to about 2GiB of RAM (plus corresponding CPU, networking, etc.), and Aurora can seamlessly scale up or down to meet demand according to your configurations.&lt;/p&gt;

&lt;p&gt;You incur a cost (about $0.12 per hour) as long as the ACU is provisioned. So at the previously cheapest level (0.5 ACU's), you're running up a $43.80 monthly bill, even with zero requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  👻 Defining "Serverless"
&lt;/h2&gt;

&lt;p&gt;Serverless is a technology with a problem: There's no universally accepted definition of what 'serverless' is. Ben Kehoe captures this perfectly in &lt;a href="https://ben11kehoe.medium.com/the-meaning-lessness-of-serverless-cc004936dee5" rel="noopener noreferrer"&gt;The Meaning(lessness) of Serverless&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For this scenario though, we need a framework to assess this against:&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%2Fkvfalqh58abw3flz1bpp.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%2Fkvfalqh58abw3flz1bpp.png" alt="Momento's Litmus Test for Serverless" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The team at &lt;a href="https://www.gomomento.com/" rel="noopener noreferrer"&gt;Momento&lt;/a&gt; came up with their &lt;a href="https://www.gomomento.com/blog/fighting-off-fake-serverless-bandits-with-the-true-definition-of-serverless/" rel="noopener noreferrer"&gt;Litmus Test for Serverless&lt;/a&gt;, which I'll use as our gold standard of 'pure serverless'.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚙️ How it Works
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://aws.amazon.com/blogs/database/introducing-scaling-to-0-capacity-with-amazon-aurora-serverless-v2/" rel="noopener noreferrer"&gt;official launch blog&lt;/a&gt; by AWS does its usual good job at covering the key information. Here's how scale-to-zero works in a nutshell:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;With 0 ACUs, Aurora Serverless v2 DB instances can automatically pause after a period of inactivity. Aurora pauses an Aurora Serverless v2 instance if it doesn’t have connections initiated by user activity within the speciﬁed time period. For the paused duration, there are no charges for compute as the database is at 0 ACUs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a change from previous releases, where you needed at least 0.5 ACU's - incurring a permanent minimum cost. If the database isn't used&lt;sup&gt;*&lt;/sup&gt;, you won't be paying for it. When new connections are received, it'll start up again.&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%2Fj5s5xexocq4iyopmtz01.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%2Fj5s5xexocq4iyopmtz01.png" alt="Example of how the scaling works" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Documentation also refers to this as &lt;strong&gt;auto-pause&lt;/strong&gt;, which is very descriptive of the underlying mechanism. It's effectively pausing the database instance, since it's not in use.&lt;/p&gt;

&lt;h3&gt;
  
  
  👀 Caveats
&lt;/h3&gt;

&lt;p&gt;There's a &lt;em&gt;lot&lt;/em&gt; to know about what counts as being "used". Again to their credit, AWS lays it both in their &lt;a href="https://aws.amazon.com/blogs/database/introducing-scaling-to-0-capacity-with-amazon-aurora-serverless-v2/" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; and much deeper in the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2-auto-pause.html" rel="noopener noreferrer"&gt;Aurora docs&lt;/a&gt;; but to capture a few very interesting points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Any open connections prevents pausing&lt;/li&gt;
&lt;li&gt;Use of Replication and/or &lt;a href="https://aws.amazon.com/rds/proxy/" rel="noopener noreferrer"&gt;RDS Proxy&lt;/a&gt; also prevents pausing&lt;/li&gt;
&lt;li&gt;Any connection attempt will cause the instance to resume&lt;/li&gt;
&lt;li&gt;Resuming instances takes up to 15 seconds&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These make sense given the underlying mechanisms, but this might be a surprise and remove a few use cases.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; Originally I'd mentioned that this effectively prevented use with Lambda Functions due to RDS Proxy. AWS Serverless Hero &lt;a href="https://aws.amazon.com/developer/community/heroes/michael-walmsley/" rel="noopener noreferrer"&gt;Michael Walmsley&lt;/a&gt; pointed out that this is still possible with the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html" rel="noopener noreferrer"&gt;Aurora Data API&lt;/a&gt;! 👀&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There's also a lot of specific recommendations depending on your cluster design, so as always the documentation is worth digging into before taking this to production.&lt;/p&gt;

&lt;h2&gt;
  
  
  🥶 (Very) Cold Starts
&lt;/h2&gt;

&lt;p&gt;Cold starts are a &lt;a href="https://www.readysetcloud.io/blog/allen.helton/lets-stop-talking-about-serverless-cold-starts/" rel="noopener noreferrer"&gt;persistent challenge of serverless&lt;/a&gt;, usually very solvable within the service. But for this case, we get positively arctic.&lt;/p&gt;

&lt;p&gt;Instances take up to 15 seconds to resume, and ensuring a long-enough connection timeout will be necessary to prevent unhappy consumers. This has been discussed plenty.&lt;/p&gt;

&lt;p&gt;One thing nobody seems to have talked about though is the &lt;strong&gt;Deep Sleep&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If an Aurora Serverless v2 instance remains paused more than 24 hours, Aurora can put the instance into a deeper sleep that takes longer to resume. In that case, the resume time can be &lt;strong&gt;30 seconds or longer&lt;/strong&gt;, roughly equivalent to doing a reboot of the instance.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Yikes&lt;/em&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%2Fy4kqwuzvgrq4o01upno2.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%2Fy4kqwuzvgrq4o01upno2.png" alt="Aurora Cold Start Time Diagram" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This might not be the death-blow you'd expect - there are plenty of systems using SQL that aren't sensitive to long connection times; primarily system-to-system communications. But using it on human users would not be pleasant.&lt;/p&gt;

&lt;p&gt;So let's try exactly that!&lt;/p&gt;

&lt;h2&gt;
  
  
  🧪 Experimenting with WordPress
&lt;/h2&gt;

&lt;p&gt;First thought, how viable would this be to run a WordPress instance? Spoiler: Not very.&lt;/p&gt;

&lt;p&gt;The cold start times make it a painful experience. Page load times aren't just a fluff metric either; &lt;a href="https://www.cloudflare.com/en-gb/learning/performance/more/website-performance-conversion-rates/" rel="noopener noreferrer"&gt;poor loading times do impact conversion rates&lt;/a&gt;, so while you're saving money on infrastructure, you're probably losing exponentially more from lost revenue.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any time you're not paying for the ACU's, you will pay with a guaranteed future cold start.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One thing I notice is that while you can configure it to shut down after 5 mins for maximum savings, you might choose to set that far longer just to avoid those cold starts.&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%2Fakergbxyc71vkorhnbc2.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%2Fakergbxyc71vkorhnbc2.png" alt="Setting up Aurora Serverless V2 for Scale-to-Zero" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Periodic reporting databases, where you might have many internal users slamming an application for a few days a month, but otherwise sits virtually unused. Set to a full 24 hours, most users would never see the difference.&lt;/p&gt;

&lt;p&gt;For a typical solo WordPress site though, it'd be cheaper and more consistent to run both web server and database on a single EC2 instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;tl;dr:&lt;/strong&gt; It's definitely &lt;em&gt;more&lt;/em&gt; serverless, but not "&lt;em&gt;pure&lt;/em&gt; serverless". And I don't think that's a problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/gbengelebs/unboxing-a-database-how-databases-work-internally-155h"&gt;Databases are complicated&lt;/a&gt;, and "just making it serverless" is a hard problem. And while some solutions like &lt;a href="https://www.cockroachlabs.com/product/overview/" rel="noopener noreferrer"&gt;CockroachDB&lt;/a&gt; make huge strides - check out &lt;a href="https://www.youtube.com/watch?v=HGv7bMe3suw" rel="noopener noreferrer"&gt;this video&lt;/a&gt; where they explain how they scale.&lt;/p&gt;

&lt;p&gt;"The right tool for the right job" is the motto of the wise architect. In similar cases, I'd also consider a &lt;a href="https://www.alexdebrie.com/posts/dynamodb-single-table/" rel="noopener noreferrer"&gt;single-table DynamoDB&lt;/a&gt; or even &lt;a href="https://www.sqlite.org/" rel="noopener noreferrer"&gt;SQLite&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even if this isn't 'pure serverless', this is a huge improvement that might make it just the right tool for your use case.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>GenStack - Bring PartyRock apps to your place</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Wed, 17 Jan 2024 12:17:17 +0000</pubDate>
      <link>https://dev.to/aws-builders/partysmith-bring-partyrock-apps-to-your-place-1mpn</link>
      <guid>https://dev.to/aws-builders/partysmith-bring-partyrock-apps-to-your-place-1mpn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Update:&lt;/strong&gt; By request of Amazon's legal team, the original name 'PartySmith' has been changed to &lt;strong&gt;GenStack&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://partyrock.aws/" rel="noopener noreferrer"&gt;Amazon PartyRock&lt;/a&gt; is a really cool concept, allowing you to build Generative AI applications using a clean visual UI, and removing all coding from the process, except the key parts of handling prompts. But it's had one problem - you can't take it with you.&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%2Fh4je3apjd4tdvg5iuxrz.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%2Fh4je3apjd4tdvg5iuxrz.png" alt="Diagram showing PartyRock app being processed into a generated app" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As part of Developer Experience month, I've built &lt;a href="https://genstack.ssennett.net/" rel="noopener noreferrer"&gt;🔨&lt;strong&gt;GenStack&lt;/strong&gt;&lt;/a&gt; (formerly known as PartySmith) - a platform that enables you to take the applications you've built with PartyRock, and host them yourself, on your own platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚦 How it Works
&lt;/h2&gt;

&lt;p&gt;First, go to &lt;a href="https://genstack.ssennett.net/" rel="noopener noreferrer"&gt;genstack.ssennett.net&lt;/a&gt;. Drop in the URL of your public PartyRock application, and that's pretty much it! You can download a ZIP file with your application ready-to-go.&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%2F22jyxmz2x59f17qrfbaq.gif" 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%2F22jyxmz2x59f17qrfbaq.gif" alt="Animated GIF showing the process of creating and downloading the ZIP file" width="864" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inside you'll find the application, built on SvelteKit, which can be readily deployed to AWS using SST, or even other providers like Vercel with other SvelteKit adapters. There's even a &lt;a href="https://github.com/ssennettau/PartySmith/blob/main/src/templateLayer/templates/primary/README.md" rel="noopener noreferrer"&gt;README file&lt;/a&gt; with all the details built right into the template.&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%2Fhny5ekwqkd0n16pety1w.gif" 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%2Fhny5ekwqkd0n16pety1w.gif" alt="Animated GIF showing the process of setting up and running the generated app" width="864" height="858"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it! In fact, you can see the &lt;a href="https://demo.partysmith.ssennett.net/" rel="noopener noreferrer"&gt;Demonstration App&lt;/a&gt; built around the &lt;a href="https://partyrock.aws/u/nadino/xEljGaHQr/Costume-Theme-Designer/snapshot/VRuSGss6V" rel="noopener noreferrer"&gt;Costume Theme Designer&lt;/a&gt; PartyRock app by AWS Community Builder &lt;a href="https://www.linkedin.com/in/ronak-reyhani" rel="noopener noreferrer"&gt;Nadia Reyhani&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For engineers who want to experiment with Amazon Bedrock that they can host themselves, but skip having to build a whole application, this is a handy intermediate step.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 How it REALLY works
&lt;/h2&gt;

&lt;p&gt;If you're a technical person, you probably want some of the inner-workings. So, let's talk details:&lt;/p&gt;

&lt;h3&gt;
  
  
  🗺️ Defining the Application
&lt;/h3&gt;

&lt;p&gt;When you build an application on PartyRock, everything you've setup is defined into a JSON file, which looks something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"result"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"appId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;uniqueAppId&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ssennettau"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"creationDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-01T00:00:00.0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"definition"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"widgets"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text-input"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Input Thing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"placeholder"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Write stuff here with the placeholder"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"defaultValue"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"x"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"y"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"inferred-text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Summarized Thing"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"width"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"height"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Summarize the following thing:&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;[Input Thing]&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                            &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bedrock-claude-v2"&lt;/span&gt;&lt;span class="w"&gt;
                        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Random Testing App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"lastModifiedDate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2024-01-01T00:00:00.0000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;widgets&lt;/code&gt; lists all of the different components you've added to your PartyRock app. In this case, it accepts a text input from the user, and uses Claude to output the summarized results.&lt;/p&gt;

&lt;p&gt;This is the basis of how the app works, using this as a blueprint for the various widgets.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎨 Styling
&lt;/h3&gt;

&lt;p&gt;GenStack apps come with a stylesheet built on &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind CSS&lt;/a&gt;, so it's very easy to adapt both to a similar theme to PartyRock, but also to whatever you'd prefer to use for your application.&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%2Futax96q4hv7c11dp21oo.jpg" 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%2Futax96q4hv7c11dp21oo.jpg" alt="Comparison of app without CSS, and the default provided CSS" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tailwind CSS does result in a lot of really lengthy class names, which can be a pain to work with.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"z-10 max-w-5xl w-fit items-center justify-between text-3xl font-bold lg:font-semibold pb-16 lg:flex lg:text-5xl"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To solve this, I've used &lt;code&gt;@apply&lt;/code&gt; rule's to consolidate the Tailwind Features into a single CSS stylesheet so we can use shorter and more meaningful class names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"party-header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another bonus is if you want to modify the way your app looks, it's a simple update in one place in the CSS. There's probably more best-practice ways to do this, but this is what happens when you let an ex-sysadmin write a web app - be glad I'm not using &lt;code&gt;&amp;lt;table&amp;gt;&lt;/code&gt; tags. 😅&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%2Fd35aqcc0eafu3el8k1bz.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%2Fd35aqcc0eafu3el8k1bz.png" alt="Alternative theme for Haiku Creator app" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking forward to seeing some of the things people are able to dream up!&lt;/p&gt;

&lt;h3&gt;
  
  
  🌆 State Management
&lt;/h3&gt;

&lt;p&gt;Unsurprisingly there's a lot of passing information back-and-forth in these apps, so I've had to try and plan the best way to do that. And my experience in front-end development isn't extensive, so if you have thoughts on my approach, please drop them in the comments!&lt;/p&gt;

&lt;p&gt;Typically you want to keep state management at the highest-level possible, leaving your components stateless, just populating the contents being passed to them.&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%2Fmoml6xeopr3o5lyc8y6h.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%2Fmoml6xeopr3o5lyc8y6h.png" alt="Diagram showing a parent component interacting with a State, and passing the details to the stateless child components" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This doesn't work so well here...&lt;/p&gt;

&lt;p&gt;The components in our app aren't quite as simple as they appear. Between tracking the different dependent inputs, calling Amazon Bedrock, and passing the data forward to any other components, there's a few things going on. In this case, I've flipped the concept around, with the state almost exclusively being managed within each widget.&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%2Fj0xytcj0ypcczweb2kp6.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%2Fj0xytcj0ypcczweb2kp6.png" alt="Diagram showing each component independently interacting with the State directly" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means each widget completely keeps track of what inputs it's expecting, how it should be processing it, making the call to Amazon Bedrock via our backend, displaying the result, and storing it for other widgets to use.&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%2Fib5fywv5zor9waiewp4f.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%2Fib5fywv5zor9waiewp4f.png" alt="Diagram showing the flow of the different parts of a PartySmith app widget" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This made development a constant game of whack-a-mole when dealing with complex apps, trying to track what was causing any particular type of problem.&lt;/p&gt;

&lt;p&gt;The main reason I opted for this approach was because of it's intended use for different applications. If it was a single-use app, I could code all the logic at the parent, per usual. But since this could be used with any PartyRock app, the design has to be a &lt;em&gt;lot&lt;/em&gt; more flexible than usual.&lt;/p&gt;

&lt;h3&gt;
  
  
  🛠️ Building the Builder
&lt;/h3&gt;

&lt;p&gt;This project really turned into two projects - first building the prototype target app which runs a PartyRock definition, and secondly the app to build those apps. Let's talk about the latter.&lt;/p&gt;

&lt;p&gt;Code Generators aren't anything new, but it was something I haven't done before. Breaking the problem down into pieces, apps are generated effectively in layers.&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%2Fzdb03wgfy6zwsu14inks.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%2Fzdb03wgfy6zwsu14inks.png" alt="Diagram showing the layers that are used to build the apps" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;primary&lt;/code&gt; layer is the basic app in SvelteKit, absent the app definition file. In any app, first a copy of this template layer is taken and copied to a temp directory, and a copy of the definition file from the PartyRock source app is loaded into the necessary folder.&lt;/p&gt;

&lt;p&gt;The additional features, like stylesheets or SST being baked-in have their own template layers, which will be copied in over-the-top of any existing files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get the templated package.json&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packageJsonFile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tempPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package.json&lt;/span&gt;&lt;span class="dl"&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;packageJsonContents&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;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;packageJsonFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;packageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageJsonContents&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add the necessary packages&lt;/span&gt;
&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^8.4.32&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;tailwindcss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^3.4.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Commit the updated contents of the file&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packageJsonFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;packageJson&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, any files like &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;README.md&lt;/code&gt; will be updated to reflect the necessary updates. This was less intensive than I'd expected, and often accomplished with some simple regex and file manipulation.&lt;/p&gt;

&lt;p&gt;All of the code is wrapped up in &lt;a href="https://github.com/ssennettau/PartySmith/blob/main/src/routes/api/build-app/builder.ts" rel="noopener noreferrer"&gt;builder.ts&lt;/a&gt;, with &lt;code&gt;buildGenStackApp&lt;/code&gt; orchestrating the steps of the process. I had plans to refactor this code to make it a bit cleaner, but this project has taken far longer than I'd planned, so it's not been as high on the priority list.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐌 Limitations
&lt;/h2&gt;

&lt;p&gt;Unsurprisingly, this doesn't give the whole PartyRock experience that you know and love. Namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🖼️ You can't do any visual editing&lt;/strong&gt; - Everything is down to the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📦 Layouts aren't retained&lt;/strong&gt; - Just a single column layout by default.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🌏 Source app needs to be public&lt;/strong&gt; - Unable to handle private apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;💰 Amazon Bedrock isn't free&lt;/strong&gt; - Your &lt;a href="https://aws.amazon.com/bedrock/pricing" rel="noopener noreferrer"&gt;costs&lt;/a&gt; are your own, so take care.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Partly that's by design, because PartyRock is an awesome platform and I don't want to take away from that - this is just a bonus. The other part is that it'd take a long time to build, so I'm not going to re-invent (hah) AWS's perfectly good wheel.&lt;/p&gt;

&lt;p&gt;For the layout, keeping it to a single column makes the code a lot easier to follow and modify. I'm sure there's ways to build it a lot more flexibly, but my attempts made the code a lot harder to follow.&lt;/p&gt;

&lt;p&gt;Since the apps will run using Amazon Bedrock in your account, you will also need to ensure &lt;a href="https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html" rel="noopener noreferrer"&gt;Model Access&lt;/a&gt; has been setup for the necessary foundation models.&lt;/p&gt;

&lt;h2&gt;
  
  
  🫵 Wrap-up
&lt;/h2&gt;

&lt;p&gt;The goal is to take your experiments to the next-level with minimal friction. Here's a few things that came to mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy an internal-facing corporate app in a VPC&lt;/li&gt;
&lt;li&gt;Build an MVP for a more extensive public app&lt;/li&gt;
&lt;li&gt;Highly customized personal productivity apps&lt;/li&gt;
&lt;li&gt;Add payment processing and auth for monetization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;PartyRock is an awesome creation by the team at AWS, and I hope this fills a niche to make it even more useful. And if the team want to take this as an idea to build an official version, I call that a win.&lt;/p&gt;

&lt;p&gt;Lastly, this was also a chance to stretch my skills deeper into frontend development, something I'm not the best at. If anyone wants to make improvements, forks, or branch of a whole separate version into React/Next.Js or whatever, please do so, and let me know so I can follow along!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ai</category>
      <category>svelte</category>
      <category>coding</category>
    </item>
    <item>
      <title>The Optus Outage: Business Continuity Lessons for Organizations</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Thu, 09 Nov 2023 04:53:43 +0000</pubDate>
      <link>https://dev.to/ssennettau/the-optus-outage-business-continuity-lessons-for-organizations-1815</link>
      <guid>https://dev.to/ssennettau/the-optus-outage-business-continuity-lessons-for-organizations-1815</guid>
      <description>&lt;p&gt;Yesterday in Australia, huge portions of the country were left without phone or internet access when a massive telecommunications outage by Optus impacted &lt;a href="https://www.abc.net.au/news/2023-11-09/how-the-optus-outage-played-out/103079768" rel="noopener noreferrer"&gt;over 10 million customers&lt;/a&gt;, including thousands of organizations of all sizes across the country.&lt;/p&gt;

&lt;p&gt;What are some key lessons about Business Continuity that organizations might take away from this event?&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%2Fqj51mmnqskynh8ilhbic.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%2Fqj51mmnqskynh8ilhbic.png" alt="Image" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What will fail?
&lt;/h2&gt;

&lt;p&gt;First, we need to consider what might go wrong that could impact our business.&lt;/p&gt;

&lt;p&gt;Okay, how could &lt;em&gt;anyone&lt;/em&gt; plan to deal with a national telecomm provider breaking connections for 10,000,000 customers, and knocking their business offline? The good news is you don't have to. The bad news is the scale doesn't matter as much as you think. &lt;/p&gt;

&lt;p&gt;So let's think about the biggest categories of hazards business face:&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Technological
&lt;/h3&gt;

&lt;p&gt;Losing your internet connection is a problem for a modern organization of any size, in any sector. Whether it was a whole country being knocked offline, or just your business, the impact is the same to your bottom-line.&lt;/p&gt;

&lt;p&gt;Beyond that, technology risks extend through everything from other service providers going down, the iPad powering your POS suddenly not turning on, or a tradie accidentally knocking out all electrical power to your premises.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⛈️ Natural
&lt;/h3&gt;

&lt;p&gt;Natural hazards have some obvious causes with extreme weather, like storms, heatwaves, blizzards, and many more. And of course, we've all just lived through a global pandemic. Your exposure ultimately depends on your work.&lt;/p&gt;

&lt;p&gt;Retail and hospitality will see demand reduced by severe weather, and events may need to be cancelled entirely. Logistics businesses can be extremely exposed by transport challenges. Even geological risks like earthquakes became a huge concern for many organizations - especially governments and large building-owners.&lt;/p&gt;

&lt;h3&gt;
  
  
  🤷 Humans
&lt;/h3&gt;

&lt;p&gt;Surprising nobody, humans are our own risk category. Consider the three categories already covered, even due to accidents: If extreme weather blocks the roads, employees can't get the work, illness requires them to take time off, or an accidental mistake causes a technological problem.&lt;/p&gt;

&lt;p&gt;But the most terrifying human risks are the intentional ones. This could be internal, like insider attacks or criminal acts, or external risks like cybersecurity breaches or regular theft.&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%2Fd9lb6on9clwb7djd4ykg.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%2Fd9lb6on9clwb7djd4ykg.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when it fails?
&lt;/h2&gt;

&lt;p&gt;Your organization has critical systems and business processes that it relies on. After thinking about what could happen, we need to think about how those events would impact our business processes.&lt;/p&gt;

&lt;p&gt;Start by identifying your core activities, and what's necessary to make them work. Let's go with some common activities in most organizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rostering staff for shifts&lt;/li&gt;
&lt;li&gt;Delivering service to customers&lt;/li&gt;
&lt;li&gt;Handling customer payments&lt;/li&gt;
&lt;li&gt;Receiving goods from suppliers&lt;/li&gt;
&lt;li&gt;Processing payroll to staff&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any of these processes failing would be a major problem for our organizations, and how they work will be different for every business.&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%2F1ynf9hxt8403qnqo7k92.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%2F1ynf9hxt8403qnqo7k92.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What should we do when it fails?
&lt;/h2&gt;

&lt;p&gt;No matter what, eventually something in our organization will break. It's just a matter of what will break, when will it break, and when will it happen.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Everything fails, all the time"&lt;br&gt;
Werner Vogels (CTO, Amazon.com)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Fortunately, even if a single system or process fails, the actual activity that we need to deliver often isn't completely prevented - there are alternatives we can explore.&lt;/p&gt;

&lt;p&gt;But we need to explore them &lt;em&gt;before&lt;/em&gt; the incident occurs, so we have a plan for how to react. We also need to exercise these scenarios, to see where they may not work as intended, and so people are familiar with what to do.&lt;/p&gt;

&lt;p&gt;Let's look through a few scenarios:&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%2Fx190uherqf7zfcg0lw2v.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%2Fx190uherqf7zfcg0lw2v.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💳 EFTPOS Terminal Failure at Local Café
&lt;/h3&gt;

&lt;p&gt;Most people don't carry cash in 2023, and EFTPOS is vital to retail and hospitality businesses. When these machines break, it's a big problem. In this case, we don't know what's gone wrong - just that it's stopped working.&lt;/p&gt;

&lt;p&gt;There's a few steps we could try. With hindsight and context, we might consider them "obvious", but that's never something we should assume, especially in a crisis situation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attempt the transaction a second time&lt;/li&gt;
&lt;li&gt;Reboot the EFTPOS terminal&lt;/li&gt;
&lt;li&gt;Try another EFTPOS terminal (if available)&lt;/li&gt;
&lt;li&gt;Check for an internet outage&lt;/li&gt;
&lt;li&gt;Enable S&amp;amp;F offline mode (if supported)&lt;/li&gt;
&lt;li&gt;Use manual EFTPOS vouchers (if available)&lt;/li&gt;
&lt;li&gt;Contact the bank/provider&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There's also things we might need to consider ahead of time in our planning, such as whether our business has additional EFTPOS machines, or whether we'd be comfortable with enabling Store &amp;amp; Forward on our terminals. If we use manual vouchers, our staff would also need to know how to use them.&lt;/p&gt;

&lt;p&gt;This doesn't mean you must take time for every staff member needs to be deeply familiar with the least-likely circumstances of writing the vouchers. But would it be reasonable that the duty supervisors are at least familiar with them?&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%2Fbwgc5pn12poaxnr2ajtp.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%2Fbwgc5pn12poaxnr2ajtp.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚠️ Cloud Outage at Global SaaS Software Provider
&lt;/h3&gt;

&lt;p&gt;Most of my regular audience are cloud computing experts, and we're all very acquainted with the fact that stuff breaks a lot.&lt;/p&gt;

&lt;p&gt;Let's take a look this time at the mitigation aspect, and what we can do &lt;strong&gt;before&lt;/strong&gt; an incident takes place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the application has been architected for fault-tolerance&lt;/li&gt;
&lt;li&gt;Consider cross-geographical global deployments&lt;/li&gt;
&lt;li&gt;Develop rigorous regular testing conditions (chaos engineering)&lt;/li&gt;
&lt;li&gt;Ensure inter-service dependencies are well-mapped and understood&lt;/li&gt;
&lt;li&gt;Deploying warm or cold standby's that can be activated in case of failures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these can be useful, but all come with risks, costs, and trade-off's. Standby's, even cold, are going to cost money, depending on the RTO/RPO required. Deploying solutions globally may not be possible, depending on infrastructure availability and data sovereignty requirements.&lt;/p&gt;

&lt;p&gt;We're not just talking about Disaster Recovery or Fault Tolerance either - that's just the technology. These need to be incorporated within the holistic continuity of the business itself too.&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%2F5nhpthcpcl7ujb6yswxt.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%2F5nhpthcpcl7ujb6yswxt.png" alt="Image description" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Business Continuity isn't a simple topic. In fact there's a &lt;a href="https://en.wikipedia.org/wiki/Business_continuity_planning" rel="noopener noreferrer"&gt;whole field&lt;/a&gt; associated with it. Even if you're not looking at developing a full &lt;a href=""&gt;Business Continuity Plan&lt;/a&gt;, it's worth looking at &lt;a href="https://www.thebci.org/knowledge/introduction-to-business-continuity.html" rel="noopener noreferrer"&gt;the basics&lt;/a&gt; of the topic for your organization, no matter your industry or scale.&lt;/p&gt;

&lt;p&gt;Mitigating risks has costs, in both time and money. The question is whether a risk is likely enough to occur that it's worth the costs to offset.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>AWS Data Engineer Associate Certification - Coming Soon</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Wed, 27 Sep 2023 04:14:36 +0000</pubDate>
      <link>https://dev.to/ssennettau/aws-data-engineer-associate-certification-coming-soon-3gbf</link>
      <guid>https://dev.to/ssennettau/aws-data-engineer-associate-certification-coming-soon-3gbf</guid>
      <description>&lt;p&gt;The &lt;a href="https://aws.amazon.com/certification/certified-data-engineer-associate/" rel="noopener noreferrer"&gt;AWS Certified Data Engineer - Associate&lt;/a&gt; has been announced with the beta exam is opening in Q4 2023, with the final release due in Q2 2024.&lt;/p&gt;

&lt;p&gt;Let's break down the new certification, analyze what it's going to look like, dig into what it means for AWS professionals.&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%2Fauojzexx6synbdsuhpw2.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%2Fauojzexx6synbdsuhpw2.png" alt="People standing around a whiteboard talking about a diagram" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📋 Knowledge and Skills Covered
&lt;/h2&gt;

&lt;p&gt;AWS Certification Exams categorize skills and knowledge into distinct domains, each focusing on key concepts of the subject.&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%2Ftyaf46nqi6y4gaqbytn4.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%2Ftyaf46nqi6y4gaqbytn4.png" alt="Breakdown of the domains in DEA-C01" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a quick overview of some prominent services within each domain, providing insight into the certification's scope. They focus heavily on the Analytics service family, although it really does cover services across all steps of the data cycle.&lt;/p&gt;

&lt;p&gt;Interestingly, &lt;a href="https://aws.amazon.com/cdk/" rel="noopener noreferrer"&gt;AWS CDK&lt;/a&gt; and &lt;a href="https://aws.amazon.com/serverless/sam/" rel="noopener noreferrer"&gt;SAM&lt;/a&gt; are both explicitly mentioned. While CDK broadly addresses Infrastructure as Code, SAM is highlighted for its role in developing &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/aws-serverless-data-analytics-pipeline/aws-serverless-data-analytics-pipeline.html" rel="noopener noreferrer"&gt;serverless data pipelines&lt;/a&gt; - a hugely underrated concept.&lt;/p&gt;

&lt;p&gt;For more details, check out the &lt;a href="https://d1.awsstatic.com/training-and-certification/docs-data-engineer-associate/AWS-Certified-Data-Engineer-Associate_Exam-Guide.pdf" rel="noopener noreferrer"&gt;DEA-C01 exam guide&lt;/a&gt; available from AWS.&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%2Fhnxylhs1kjudk2yz6m3l.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%2Fhnxylhs1kjudk2yz6m3l.png" alt="Person pointing at a location on a map" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗺 Certification Pathway
&lt;/h2&gt;

&lt;p&gt;This certification opens a new pathway to broaden expertise in AWS's data services; great news for those with data-centric backgrounds.&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%2Fbebkv8ew19hsiq8ze19x.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%2Fbebkv8ew19hsiq8ze19x.png" alt="Potential certification pathway for AWS Certified Data Engineer and beyond" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This serves as an ideal stepping stone for individuals without data backgrounds aiming to delve into advanced Specialty topics. Conversely, for data professionals, this certification provides an excellent opportunity to expand their AWS knowledge within a familiar context using specialist services they're likely acquainted with.&lt;/p&gt;

&lt;p&gt;While it was always possible to acquire these skills without certification, the introduction of a structured pathway incentivizes learners to pursue certification and encourages training providers to fill the skill gap.&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%2Fsik2qjdv4p63bdzqh4u7.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%2Fsik2qjdv4p63bdzqh4u7.png" alt="Person sitting in a bleak empty room looking at the computer screen" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  💻 No Practical Assessments
&lt;/h2&gt;

&lt;p&gt;The AWS Certified Data Engineer - Associate exam reverts to the traditional Multiple Choice format, devoid of any practical hands-on assessment.&lt;/p&gt;

&lt;p&gt;Since first introducing exam labs in 2021 for the &lt;a href="https://aws.amazon.com/certification/certified-sysops-admin-associate/" rel="noopener noreferrer"&gt;SysOps Associate exam&lt;/a&gt;, AWS has temporarily suspended the lab component as of March 2023, pending changes to the platform.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This removal of exam labs is temporary while we evaluate the exam labs and make improvements to provide an optimal candidate experience. With this change, the exam will consist of 65 multiple-choice questions and multiple-response questions, with an exam time of 130 minutes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is disappointing, especially at the Associate-level where testing practical skills adds a lot to the value of a certification. But from experience with other vendors, a bad experience is &lt;em&gt;far&lt;/em&gt; more damaging. Still, I am hoping we see this feature return in 2024.&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%2F6k5pcnsu8wi27zs7zb15.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%2F6k5pcnsu8wi27zs7zb15.png" alt="Woman studying on her phone while standing in busy public transport" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Preparing for the Exam
&lt;/h2&gt;

&lt;p&gt;Right now in September 2023, there are no courses yet available for the exam since it's just been announced, although I'd expect some to be available around the time of the final release. The beta exam will be available soon, but I have a big tip:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait until after March 2024 to sit the exam.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beta exams are notoriously tough and prone to issues. Plus, you have to wait for weeks or even months for your results. Unless you're a trainer or otherwise just extremely eager, it's generally wiser to wait for the final release.&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%2Foq7uyua9g3li59169eqc.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%2Foq7uyua9g3li59169eqc.png" alt="Visualization of an island surrounded by data" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Certifications are strategic tools for vendors, directing attention to specific subjects. Given the current data and AI landscape, an Associate-level certification focused on Data is a logical step.&lt;/p&gt;

&lt;p&gt;However, AWS's persistent focus on role-based certifications at the Associate and Professional levels, such as "Data Engineer", is a point of critique. It might be more constructive to center these certifications around broader disciplines or knowledge areas. This approach not only lays a solid foundation for advanced skills but also minimizes confusion about job roles (looking at you, Solution Architect - Associate).&lt;/p&gt;

&lt;p&gt;If you're considering furthering your AWS knowledge, this new certification is worth contemplating, and its creation is a positive move by AWS.&lt;/p&gt;

&lt;p&gt;Sorry future-&lt;a href="https://www.linkedin.com/posts/sammy-cheung_aws-awsambassador-awsgoldjacket-activity-7110150138865598465-bnbW/" rel="noopener noreferrer"&gt;golden jacket&lt;/a&gt; holders.. But at least this has more universal relevance than the SAP Specialty 🙃&lt;/p&gt;

</description>
      <category>aws</category>
      <category>certification</category>
    </item>
    <item>
      <title>AI Coding Companions: My Experiences in 2023</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Tue, 26 Sep 2023 06:22:28 +0000</pubDate>
      <link>https://dev.to/aws-builders/ai-coding-companions-my-experiences-in-2023-j3p</link>
      <guid>https://dev.to/aws-builders/ai-coding-companions-my-experiences-in-2023-j3p</guid>
      <description>&lt;p&gt;One moment, it's like having your thoughts magically transcribed into code right before your eyes. The next, it's like a monkey with a typewriter belting out the whimsical rhymes of Dr. Seuss. Welcome to the wild and surprising world of AI Coding Companion tools!&lt;/p&gt;

&lt;p&gt;Over the last year, I've been using &lt;a href="https://aws.amazon.com/codewhisperer/" rel="noopener noreferrer"&gt;Amazon CodeWhisperer&lt;/a&gt;, &lt;a href="https://github.com/features/copilot" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;, and &lt;a href="https://chat.openai.com/" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt; in various ways to make my hacky coding easier and more effective. With that, I've condensed my experiences into some key reflections that have definitely made my life easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Writing Boilerplate Code
&lt;/h2&gt;

&lt;p&gt;One of the things AI solutions excel at can best be described as "making the boring stuff go faster". We're already familiar with this, but instead of going through the vendor docs or Stack Overflow, we can skip a few steps.&lt;/p&gt;

&lt;p&gt;This is great for things like API calls (like writing out an &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html" rel="noopener noreferrer"&gt;S3 Object Upload&lt;/a&gt; call), writing out some logic flows, and a lot of the proforma that isn't necessarily challenging, but just takes time.&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%2Fk675hz9mf3htlrdw0u96.jpg" 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%2Fk675hz9mf3htlrdw0u96.jpg" alt="Python code written in visual studio showing a PutItem call being made to S3 suggested by CodeWhisperer in Autocomplete" width="687" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These suggestions can include errors which may not be immediately obvious. That isn't much of a problem when you're familiar with the topic, but when you're not...&lt;/p&gt;

&lt;h2&gt;
  
  
  ❌ Handling Unfamiliar Concepts
&lt;/h2&gt;

&lt;p&gt;Nobody is an expert at everything, but when writing code, you should definitely have some understanding of what you're trying to accomplish. AI tools let us shortcut this a bit, but it also magnifies the problems.&lt;/p&gt;

&lt;p&gt;Recently I needed to build something with Python and &lt;a href="https://ffmpeg.org/" rel="noopener noreferrer"&gt;FFmpeg&lt;/a&gt;. And while FFmpeg is amazingly powerful, it can also be incredibly complicated.&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%2Fim8b9xtil2fxzrq7tutz.jpg" 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%2Fim8b9xtil2fxzrq7tutz.jpg" alt="Attempt at using CodeWhisperer to generate an action with FFmpeg" width="800" height="124"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Trying to troubleshoot these errors was next-to impossible without knowing more about how FFmpeg actually worked, so I ended up going back and writing everything by hand. That said, even this process can be made easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧠 Troubleshooting Code Issues
&lt;/h2&gt;

&lt;p&gt;Writing code can be hard, and especially when dealing with new languages, you can just get things wrong. And surprisingly, one of the best tools to help with this has been ChatGPT.&lt;/p&gt;

&lt;p&gt;Because of the extensive capabilities of the GPT4 model and the gargantuan corpus that powers it, ChatGPT is actually able to help pinpoint why some chunks of code didn't work as expected. Case in point, it was very helpful when I was trying to get some Flutter/Dart code working in an experience I posted about on &lt;a href="https://www.linkedin.com/posts/ssennettau_okay-so-today-i-actually-used-chatgpt-to-activity-7072452548925743104-Hk_w" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&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%2Ftseor15xjvgfojgw15fm.jpg" 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%2Ftseor15xjvgfojgw15fm.jpg" alt="Screenshot of a ChatGPT session asking why some code was not working, a snippet of some Dart code, and the insightful response returned by ChatGPT" width="773" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uploading a code snippet for a personal side project to ChatGPT isn't much of an issue, but it does speak to a lot of concerns that people have around one very major relevant topic...&lt;/p&gt;

&lt;h2&gt;
  
  
  🔐 Security Implications
&lt;/h2&gt;

&lt;p&gt;Uploading highly sensitive code into an unknown API that is given full access to your hard work is unnerving, and does come with risks. Especially in the corporate context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/codewhisperer/latest/userguide/sharing-data.html" rel="noopener noreferrer"&gt;Amazon CodeWhisperer&lt;/a&gt;, &lt;a href="https://docs.github.com/en/enterprise-cloud@latest/copilot/overview-of-github-copilot/about-github-copilot-for-individuals#about-privacy-for-github-copilot-for-individuals" rel="noopener noreferrer"&gt;GitHub Copilot&lt;/a&gt;, and &lt;a href="https://openai.com/blog/new-ways-to-manage-your-data-in-chatgpt" rel="noopener noreferrer"&gt;ChatGPT&lt;/a&gt; can all be configured to prevent it from learning from your inputs (check the links for more info). And while you’re probably already trusting these organizations with storing your data anyway (especially AWS and GitHub/Microsoft), but the risks of it being given to other customers is where the danger lies.&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%2Ftpswr6r1y2g9g80fqkxg.jpg" 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%2Ftpswr6r1y2g9g80fqkxg.jpg" alt="Checkbox in the Amazon CodeWhisperer settings in Visual Studio Code that prevents it from learning from your code" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether your organization deems the use of AI coding tools acceptable depends on a lot of factors (legislative, compliance, regulatory, etc.), but if there's PII or commercially sensitive information, I'd err on the side of caution.&lt;/p&gt;

&lt;h2&gt;
  
  
  🖊 Documenting Code
&lt;/h2&gt;

&lt;p&gt;This was a surprising little gimmick. While we can use comments as placeholders for natural language to prompt the tool to generate code, we can also do the same in reverse too.&lt;/p&gt;

&lt;p&gt;By starting a comment above a block of text, you can prompt the model to write a description of what the function is doing within the context of the file.&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%2F08u091036759cv8eigf9.jpg" 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%2F08u091036759cv8eigf9.jpg" alt="Example showing how an autocomplete suggestion can document a function with a comment based on existing code" width="776" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This... is actually pretty cool. It's not infallible, and so far they can only read within the context of the current file. But I could see this being useful in navigating an unfamiliar codebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  😒 Fighting the UI
&lt;/h2&gt;

&lt;p&gt;Integration with the IDE makes using some of these tools incredibly easy, but not always for the better. The autocomplete suggestions can be remarkably quick while writing code. Sometimes too quick.&lt;/p&gt;

&lt;p&gt;Coding often requires a focused, uninterrupted thought process, and interruptions by autocomplete suggestions can disrupt that. Likewise, occasionally the multi-line suggestions will cause unexpected behaviour when navigating or manipulating the code you've already written.&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%2Ffy8maqaog3kqjsgqxi55.jpg" 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%2Ffy8maqaog3kqjsgqxi55.jpg" alt="Simpsons meme of Lenny stating " width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These tools are great, but often it can be useful just to hit the &lt;em&gt;Pause&lt;/em&gt; button for a while. Though I hope future updates can make these experiences more seamless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Generative AI supported development is here to stay. It's an inescapable fact, and will continue to change the nature of the industry. It's not perfect, and can create its own headaches, but it's also very much worth exploring.&lt;/p&gt;

&lt;p&gt;If you're tried some of these tools, share your thoughts in the comments! If not, I encourage you to give them a try.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Building a Serverless AI Content Detector</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Thu, 29 Jun 2023 02:10:46 +0000</pubDate>
      <link>https://dev.to/ssennettau/building-a-serverless-ai-content-detector-65d</link>
      <guid>https://dev.to/ssennettau/building-a-serverless-ai-content-detector-65d</guid>
      <description>&lt;p&gt;One remarkable byproduct of the AI proliferation boom bought about by ChatGPT is the amount of AI-generated content out there on the internet. Recently I've found a need to be able to identify them at scale, so I decided to tackle two problems at once.&lt;/p&gt;

&lt;p&gt;The AWS Community Builder Program's Machine Learning Team recently started a Hackathon around Generative AI and the Hugging Face &lt;a href="https://huggingface.co/docs/transformers/main/en/index" rel="noopener noreferrer"&gt;Transformers Library&lt;/a&gt;, so this could be a fun experiment. If you'd like to know more about the program, check my &lt;a href="https://dev.to/aws-builders/how-to-become-an-aws-community-builder-2m79"&gt;other blog post&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, I decided to build an AI Content Detection solution, and document my journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 The Solution
&lt;/h2&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%2Fqqtwzvy3ugqmzneex8ri.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%2Fqqtwzvy3ugqmzneex8ri.png" alt="Showing an example of a request and response to the API" width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The goal was to build an API which could receive a text, and provide an analysis on whether it was likely to be written by a real human, or generated by an AI.&lt;/p&gt;

&lt;p&gt;Additionally, I wanted to leverage a serverless architecture so I could easily embed it into a future event-driven solution, and to scale it effectively with minimal cost.&lt;/p&gt;

&lt;p&gt;For the Hackathon, I also wanted to provide it as a synchronous API that could return a result in a reasonable period of time, so single-second latency was important.&lt;/p&gt;

&lt;p&gt;With that, let's get into the journey of building this thing:&lt;/p&gt;

&lt;h2&gt;
  
  
  🤖 Part 1) Exploring the &lt;code&gt;transformers&lt;/code&gt; library
&lt;/h2&gt;

&lt;p&gt;First thing was to learn how the library actually works, and use it in a simple Python script. It was... amazing to get working. How simple?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;

&lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-classification&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;roberta-base-openai-detector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello! I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;m ChatGPT, a large language model trained by OpenAI. I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;m here to assist you with any questions or information you may need. How can I help you today?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...I gotta say, I'm impressed how the &lt;code&gt;transformers&lt;/code&gt; library abstracted away all of the stuff with tokenization, inference, and pytorch. Once the libraries are installed, it's a breeze to work with. Success!&lt;/p&gt;

&lt;h2&gt;
  
  
  🔨 Part 2) Getting &lt;code&gt;transformers&lt;/code&gt; into Lambda
&lt;/h2&gt;

&lt;p&gt;AWS Lambda excels natively with many different workloads. Machine Learning inference isn't one of them... Between the libraries and model totalling up into several gigabytes of dependencies, we can't exactly just toss it all into a ZIP file. At that size, even &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html" rel="noopener noreferrer"&gt;Lambda Layers&lt;/a&gt; aren't going to cut it.&lt;/p&gt;

&lt;p&gt;First I thought I could use some sneaky-jutsu by building a ZIP file of the packages which I could host on S3. At initialization, I'd use the &lt;a href="https://aws.amazon.com/blogs/aws/aws-lambda-now-supports-up-to-10-gb-ephemeral-storage/" rel="noopener noreferrer"&gt;increased ephemeral storage capacity&lt;/a&gt; to download and unzip the package. &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%2Fakwrm5lpgzn60oq4uldv.jpg" 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%2Fakwrm5lpgzn60oq4uldv.jpg" alt="Simpsons meme showing ill-conceived scheme of using S3 packaging into ephemeral storage" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But that didn't work quite so well. Between some issues with the packages, and the amount of time it took to unzip... it just wasn't worth it. So I refactored back into using &lt;a href="https://aws.amazon.com/efs/" rel="noopener noreferrer"&gt;EFS&lt;/a&gt; to host the packages and model files. &lt;/p&gt;

&lt;p&gt;This did mean I needed to build a whole VPC to come along for the ride. Really just writing a bunch of extra resources for the SAM Template and some minor costs like a NAT Gateway. Still, building a whole VPC just to make a Lambda function run better isn't ideal.&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%2Flkr1cmlcmx0b5ae41x6y.jpg" 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%2Flkr1cmlcmx0b5ae41x6y.jpg" alt="Simpsons meme of the shame of having a VPC in a modern solution" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's always &lt;em&gt;some&lt;/em&gt; reason to keep VPC's...&lt;/p&gt;

&lt;h2&gt;
  
  
  ⚡ Part 3) Orchestration with Step Functions
&lt;/h2&gt;

&lt;p&gt;Since I want to extend the functionality further, I chose to build this around a &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/concepts-standard-vs-express.html" rel="noopener noreferrer"&gt;Step Function Express Workflow&lt;/a&gt; to orchestrate the solution.&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%2Fa3ar9d3jqkalcbla2ds6.jpg" 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%2Fa3ar9d3jqkalcbla2ds6.jpg" alt="Step Function State Machine with a single step to invoke a Lambda function" width="704" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay fair enough, that's not very interesting. Instead, let's make this smarter by adding some caching functionality. API Gateway does have caching, but we want to do something more ambitious than just simple strings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/ssennettau/serverless-ai-content-detector/blob/main/docs/statemachine.png" rel="noopener noreferrer"&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%2Fzrhrxrs4thcxltukbcby.png" alt="Additional steps added to the State Machine to generate a hash and query a cache table in DynamoDB" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By keeping our individual Lambda functions short and single-purpose too, it also makes it far easier to rip out components and replace them. With the native integration of the AWS SDK, &lt;a href="https://docs.aws.amazon.com/step-functions/latest/dg/connect-ddb.html" rel="noopener noreferrer"&gt;working with DynamoDB&lt;/a&gt; is incredibly easy too.&lt;/p&gt;

&lt;p&gt;Getting API Gateway to perform a synchronous execution also doesn't integrate quite as smoothly, but one of the articles in the &lt;a href="https://serverlessland.com/patterns/step-function-sync-rest-api" rel="noopener noreferrer"&gt;Serverless Land Pattern Collection&lt;/a&gt; solved that.&lt;/p&gt;

&lt;h2&gt;
  
  
  🌐 Part 4) Downloading whole pages
&lt;/h2&gt;

&lt;p&gt;Analyzing individual strings is nice and all, but let's make this thing more powerful - I want to be able to give it a URL, and let it go do it's thing. So we just get &lt;code&gt;requests&lt;/code&gt; to download it, &lt;code&gt;bs4&lt;/code&gt; to strip the bones off, and viola, we have a page! Easy days...&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%2Ftmxi8ots8g6wp0vhie0v.jpg" 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%2Ftmxi8ots8g6wp0vhie0v.jpg" alt="Error caused by a large payload when triggering the model" width="800" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Umm, okay - maybe this is a bit more complicated after all.&lt;/p&gt;

&lt;p&gt;Webpages have a lot of elements, and not all of it is relevant. After some poking, I've stripped it back just to look at the contents of the &lt;code&gt;&amp;lt;article&amp;gt;&lt;/code&gt; tags. This could be made to support custom targeting with parameters to the request, but didn't have  a particular need in this case. But there are other problems.&lt;/p&gt;

&lt;p&gt;The model can only handle up to &lt;a href="https://huggingface.co/docs/transformers/tokenizer_summary" rel="noopener noreferrer"&gt;512 tokens at once&lt;/a&gt;, which is a bit of a challenge. Splitting up the payload to be processed in reasonable sized chunks that processed to produce meaningful results was surprisingly hard. No joke, I rewrote the damn thing about a dozen times, and it made me deeply question my skills.&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%2F104fnkxs6jyru7cbpey4.jpg" 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%2F104fnkxs6jyru7cbpey4.jpg" alt="Simpsons Meme showing  raw `chunk.py` endraw  sinking hopelessly" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Eventually, I came up with a solution that mostly works. Using the &lt;code&gt;RoBERTa&lt;/code&gt; tokenizer and breaking it down per line works &lt;em&gt;pretty&lt;/em&gt; reliably (don't check the TODO I left behind in the code).&lt;/p&gt;

&lt;p&gt;Also, first time using &lt;a href="https://aws.amazon.com/codewhisperer/" rel="noopener noreferrer"&gt;Amazon CodeWhisperer&lt;/a&gt; on a full project too, and it was a helpful little thing!&lt;/p&gt;

&lt;h2&gt;
  
  
  👀 Part 5) Observability &amp;amp; Optimization
&lt;/h2&gt;

&lt;p&gt;So, everything's done and working now, right?! Sure!&lt;/p&gt;

&lt;p&gt;Except for one problem... It takes quite a while to run. Like, stupidly long execution times, even for simple workloads.&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%2Fdup3nuvovcr46ihh7no4.jpg" 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%2Fdup3nuvovcr46ihh7no4.jpg" alt="Simpsons meme of a deeply frustrated me fighting with latency" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my eventual use case, this is minor since it'll be run asynchronously, and can take as long as it generally pleases. But that's not as great for our synchronous demo API. So it's time to enable &lt;a href="https://aws.amazon.com/xray/" rel="noopener noreferrer"&gt;AWS X-Ray&lt;/a&gt; to run the distributed tracing over the whole thing.&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%2Fa8rpiv34gfuzd5jpjh0j.jpg" 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%2Fa8rpiv34gfuzd5jpjh0j.jpg" alt="X-Ray Trace showing high latency during initialization, but low during invocations" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No surprise, but our detection function is a pure chonk (technical term), and slow as hell - especially in initialization. The invocation itself is actually relatively quick.&lt;/p&gt;

&lt;p&gt;There's many ways to tackle this problem. After a few hours looking at the underlying code, tuning the resourcing, and exploring the possibility of implementing my own snapshot system (roll on SnapStart for Lambda), I settled on one solution...&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%2F4hfc4off7s0vu17qo0ou.jpg" 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%2F4hfc4off7s0vu17qo0ou.jpg" alt="Simpsons meme of screaming in frustration and eventually deploying Provisioned Concurrency" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html" rel="noopener noreferrer"&gt;Provisioned Concurrency&lt;/a&gt; means AWS will keep several instances of the function warm and ready for invocations, bypassing the slower start times. Along with Reserved Concurrency setting an upper-limit, we shouldn't hit any bottlenecks caused by long init times.&lt;/p&gt;

&lt;p&gt;This does come with a &lt;em&gt;much&lt;/em&gt; higher cost, but for this case, it's a worthwhile trade-off. Eventually Lambda SnapStart for Python would let me work around easily being a stateless workload, but for now I'll work with what I have.&lt;/p&gt;

&lt;h2&gt;
  
  
  💪 Try it yourself!
&lt;/h2&gt;

&lt;p&gt;The API is available for use at the path below!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://hackathon.api.ssennett.net/run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd like to try it out yourself (including the curl/Powershell commands), or even fork your own copy, check out the code on GitHub under my &lt;a href="https://github.com/ssennettau/serverless-ai-content-detector/" rel="noopener noreferrer"&gt;serverless-ai-content-detector repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ✨ Building a Custom Model
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;roberta-base-openai-detector&lt;/code&gt; model isn't infallible, which they make explicitly clear in their &lt;a href="https://huggingface.co/roberta-base-openai-detector" rel="noopener noreferrer"&gt;model card&lt;/a&gt;. It was also trained on a dataset by GPT-2, which while being a technological marvel is also relatively old as hell, while the globally proliferous ChatGPT runs on GPT-3.5 and GPT-4.&lt;/p&gt;

&lt;p&gt;I did try building my own model on RoBERTa using Common Crawl and the open-source &lt;a href="https://huggingface.co/tiiuae/falcon-40b" rel="noopener noreferrer"&gt;Falcon-40B&lt;/a&gt; model, but it just wasn't reliable enough to warrant implementation. Not for lack of trying though:&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%2Fz5n17fph75g50kokufoj.jpg" 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%2Fz5n17fph75g50kokufoj.jpg" alt="Snippet of AWS costs showing $146.73 with SageMaker being the most utilized service" width="592" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank goodness for free AWS credits 😅&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 Conclusion
&lt;/h2&gt;

&lt;p&gt;In the end, this is a high-level of the solution I ended up with:&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%2F4nd0papw2pxnuyeyhuyj.jpg" 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%2F4nd0papw2pxnuyeyhuyj.jpg" alt="Image description" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was a really fun project to build.. The Hugging Face Transformers Library was surprisingly easy to use, and once I got over the hurdles, it was a breeze to use with native AWS Services.&lt;/p&gt;

&lt;p&gt;Nothing will ever detect AI generated content with complete reliability - that's a fact of the modern world. But this kind of solution can drive signals for us to investigate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let me know in the comments if you end up trying it out, and how accurate the prediction was!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>ai</category>
    </item>
    <item>
      <title>Developers Journey to AWS Lambda</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Sun, 09 Apr 2023 13:25:56 +0000</pubDate>
      <link>https://dev.to/aws-builders/developers-journey-to-aws-lambda-16ag</link>
      <guid>https://dev.to/aws-builders/developers-journey-to-aws-lambda-16ag</guid>
      <description>&lt;p&gt;AWS Lambda has a surprise learning curve. You create a new function, write your code, and it executes. Easy, right? Then you discover just how deep the rabbit hole goes. Deluged by so many topics, it's hard to know where to go next.&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%2Fgmw1r7jhkwwwkju5r85b.jpg" 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%2Fgmw1r7jhkwwwkju5r85b.jpg" alt="Dunning-Kruger style curve showing milestones relating to building with AWS Lambda" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By this point, you've started using Lambda, but have now fallen off that mountain. In this post, we'll break down five steps to get you moving along your Lambda journey.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) Improving your Code
&lt;/h2&gt;

&lt;p&gt;AWS Lambda seems simple enough - write whatever code you want, and it runs it. That's true, but not all code is created equal, and there are some important ways to elevate your code in Lambda functions.&lt;/p&gt;

&lt;p&gt;Foundational to using AWS Lambda is understanding the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtime-environment.html" rel="noopener noreferrer"&gt;execution environment&lt;/a&gt; it uses so we that can understand behaviour like cold starts, and how our code impacts them.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html" rel="noopener noreferrer"&gt;Best Practices for AWS Lambda&lt;/a&gt; is an excellent read, but to highlight the most significant points about code:&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove your logic from your handler
&lt;/h3&gt;

&lt;p&gt;Keeping your code as simple as possible removes headaches. When we start writing Lambda functions, they get lengthy, and we may keep them in the handler function.&lt;/p&gt;

&lt;p&gt;This complicates our testing since our unit testing is inextricably linked to how our function is invoked. Use your handler function to control interactions with other solution components, while your business logic is held in separate functions within your code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import requests

def check_inventory(check):
    response = request.get('http://apiurl/inventory')

    if check in response.text:
        return True
    else:
        return False

def lambda_handler(event, context):
    data = check_inventory(event['itemId'])

    return {
        'statusCode': 200,
        'body': json.dumps(data)
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, the logic for checking our inventory can be tested easily, regardless of how it's integrated into Lambda. Likewise, our handler focuses solely on how to pass the information to and from the business logic, making it easier to maintain. This is a very basic example, while AWS Chief Evangelist EMEA, Danilo Poccia has a brilliantly succinct gist, &lt;a href="https://gist.github.com/danilop/939df8b4de06eb3a0bc6ae0ca1d9387d" rel="noopener noreferrer"&gt;GreetingsAPI.js&lt;/a&gt;, that shows a more complex integration&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuration outside code
&lt;/h3&gt;

&lt;p&gt;Trying to handle configuration inside of our code is always a horrible mess. How many times have you made code that looks something like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# apiUrl = "https://prod.my-tenant.customersystem.net/v2/res/item"
apiUrl = "http://127.0.0.1:3000/mock"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even worse...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiToken = "QmFzZTY0IGlzbid0IHJlYWwgZW5jcnlwdGlvbg=="
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Okay yeah, me too... ✋ Fortunately, AWS gives us a few options to get around this with Lambda.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html" rel="noopener noreferrer"&gt;Environment Variables&lt;/a&gt; are familiar to most developers and work identically between your local machine and AWS. But for anything secure, or that needs to be used across multiple Lambda functions, it's worth checking out &lt;a href="https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html" rel="noopener noreferrer"&gt;AWS Systems Manager Parameter Store&lt;/a&gt;, &lt;a href="https://aws.amazon.com/secrets-manager/" rel="noopener noreferrer"&gt;AWS Secrets Manager&lt;/a&gt;, or &lt;a href="https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html" rel="noopener noreferrer"&gt;AWS AppConfig&lt;/a&gt;. It removes many future headaches, and helps your security team sleep at night.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leverage environment reuse
&lt;/h3&gt;

&lt;p&gt;When a new instance of your function is spun up, the &lt;code&gt;Init&lt;/code&gt; phase will run any static code outside of your functions.&lt;/p&gt;

&lt;p&gt;If you need to perform any long-running tasks before handling requests, or instantiated before receiving requests, this can make your code much more efficient. Make the most of this where you can, making things quicker for your end users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import pymysql

try:
    connection = pymsql.connect(&amp;lt;DetailsGoHere&amp;gt;)
except pymysql.MySQLError as e:
    logger.error(e)
    sys.exit()

def lambda_handler(event,context):
    with connection.cursor() as cursor:
        cursor.execute("SELECT * FROM USERS WHERE userId='" + event['uid'] + "'")
        data = connection.fetchone()
        return data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure that data leaks don't occur between invocations when handling stateful data. And even though something has been instantiated, there should still be checks, especially for database connections, to ensure they're still alive.&lt;/p&gt;

&lt;p&gt;AWS Serverless Hero Jeremy Daly's article on &lt;a href="https://www.jeremydaly.com/reuse-database-connections-aws-lambda/" rel="noopener noreferrer"&gt;Reusing Database Connections in Lambda&lt;/a&gt; from 2018 covers the concept well, although new options are available for database connection management.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Leveraging CI/CD and Frameworks
&lt;/h2&gt;

&lt;p&gt;If you're still editing and saving your code live in the AWS Console, chances are you've run into this situation:&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%2Fy38eqt12us5s3kfrzh27.jpg" 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%2Fy38eqt12us5s3kfrzh27.jpg" alt="Flowchart showing the pitfalls of uncertainty and manual handling developing with Lambda without using CI/CD" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's 2023, so you already know why you should be using a CI/CD Pipeline. But you can spend more time building and troubleshooting your pipeline than actually writing valuable code. And that's just for deploying one simple Lambda function.&lt;/p&gt;

&lt;p&gt;Fortunately, we have many frameworks and tools to help us build and deploy our serverless solutions. Each Framework has different strengths, but all aim to reduce the friction between development and deployment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://aws.amazon.com/serverless/sam/" rel="noopener noreferrer"&gt;AWS SAM (Serverless Application Model)&lt;/a&gt; smooths the deployment of serverless applications for AWS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.winglang.io/" rel="noopener noreferrer"&gt;Wing&lt;/a&gt; has built an entire language around cloud-native primitives that compiles it into another provisioning provider (currently only &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.serverless.com/" rel="noopener noreferrer"&gt;Serverless Framework&lt;/a&gt; is the original framework for building serverless apps, and still a solid choice&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getampt.com/" rel="noopener noreferrer"&gt;Ampt&lt;/a&gt; is currently in private beta, but is going deep into building a fully integrated developer platform. I'm excited about what this means for developer experience!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're familiar with CloudFormation, I'd suggest &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-getting-started-hello-world.html" rel="noopener noreferrer"&gt;AWS SAM&lt;/a&gt; as a starting point. Once Ampt exits private beta, I will start to experiment with that.&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%2Fiyjnfh675ikz0bkyvkjp.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%2Fiyjnfh675ikz0bkyvkjp.png" alt="Image of a woman watching the generated metrics and information of a complex system" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Easy Observability with PowerTools
&lt;/h2&gt;

&lt;p&gt;We're all guilty of using &lt;code&gt;print('boop')&lt;/code&gt; or &lt;code&gt;console.log('hi!')&lt;/code&gt; for debugging. This doesn't scale well in Production though. Implementing custom logging for the myriad of outputs, plus generating and handling custom metrics, involves a whole mess of extra work. Not to mention supporting distributed tracing.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-lambda-powertools/" rel="noopener noreferrer"&gt;Lambda PowerTools&lt;/a&gt; - a solution that takes only a few minutes to install in your code, and makes it incredibly easy to handle your logging, metrics, and distributed tracing, all familiarly handled in your language of choice.&lt;/p&gt;

&lt;p&gt;Observability is the difference between your solution being a big box of production mysteries and a brilliant symphony of many working parts where you can understand and address issues proactively. This is the single most straightforward and significant uplift you can give a serverless application in AWS.&lt;/p&gt;

&lt;p&gt;Highly recommend checking out the &lt;a href="https://awslabs.github.io/aws-lambda-powertools-python/2.12.0/tutorial/" rel="noopener noreferrer"&gt;Tutorial for Powertools for Python&lt;/a&gt;, which covers both Powertools, plus some AWS SAM as well!&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%2Fubes7rw0sg5gxqzz9byu.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%2Fubes7rw0sg5gxqzz9byu.png" alt="Image of a complicated control panel" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Tweaking your Deployment
&lt;/h2&gt;

&lt;p&gt;"Any sufficiently advanced technology is indistinguishable from magic" (Arthur C. Clarke). Lambda is an advanced and powerful technology, and its magic has created some common misconceptions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lambda will scale your functions infinitely&lt;/li&gt;
&lt;li&gt;Lambda execution environments will start immediately&lt;/li&gt;
&lt;li&gt;Lambda changes everything immediately when you update your code&lt;/li&gt;
&lt;li&gt;Lambda will use as many resources as it needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a closer look at how we can configure our Lambda functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Scaling with Reserved Concurrency
&lt;/h3&gt;

&lt;p&gt;Lambda does have a scaling limit. By default, that number is 1,000 concurrent executions per account. Since all Lambda functions in your account share that concurrency limit, you can reserve a maximum amount for each function with &lt;a href="https://docs.aws.amazon.com/lambda/latest/operatorguide/reserved-concurrency.html" rel="noopener noreferrer"&gt;Reserved Concurrency&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reserved concurrent can also be used to set those upper limits to prevent overwhelming downstream services that your Lambda function may be sending requests to, like API's. After all, your local coffee shop with a single barista could handle infinite orders. That is if you are okay with waiting an infinite amount of time for your coffee.&lt;/p&gt;

&lt;p&gt;You can request quota increases for your account's concurrency limits - but it's worth considering other limitations first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cold Starts and Provisioned Concurrency
&lt;/h3&gt;

&lt;p&gt;We know from our exploration of the execution environment that Lambda doesn't start new execution environments immediately - it takes time to spin them up through their Init phase. &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/provisioned-concurrency.html" rel="noopener noreferrer"&gt;Provisioned Concurrency&lt;/a&gt; is how we can ensure that a minimum number is ready for use at any time.&lt;/p&gt;

&lt;p&gt;It might be tempting just to use Provisioned Concurrency to work around cold starts, but there is one huge drawback: it's not cheap. Having execution environments on standby incurs an ongoing cost of about 25%. This sounds cheap but it adds up quickly.&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%2Fbp28x97gj255hjclm3sa.jpg" 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%2Fbp28x97gj255hjclm3sa.jpg" alt="AWS Pricing Calculator Screenshot showing the cost of Provisioned Concurrency in the example below" width="761" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Lambda Function with the standard 512MB memory and 10 provisioned concurrency instances running adds up to about $54 USD per month. That's without even adding the costs of each request and their running compute time. It's &lt;em&gt;always&lt;/em&gt; worth optimizing before jumping to Provisioned Concurrency.&lt;/p&gt;

&lt;h3&gt;
  
  
  Managing Changes with Versions and Aliases
&lt;/h3&gt;

&lt;p&gt;One of the great things about Lambda is quickly updating your code and having it reflected in your Production compute environment. That's great, but often you need a bit more control. This is where versions and aliases come in.&lt;/p&gt;

&lt;p&gt;Lambda has built-in &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-versions.html" rel="noopener noreferrer"&gt;versioning capabilities&lt;/a&gt;. When doing live editing, you're working with the &lt;code&gt;$LATEST&lt;/code&gt; version. Creating versions lets you lock your code to a specific state, which can be executed independently by its unique ARN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html" rel="noopener noreferrer"&gt;Aliases&lt;/a&gt; take this to the next level, where you can have a dynamic reference to a particular function version. If you had an alias for &lt;code&gt;prod&lt;/code&gt;, this could be the target of your invocations from your API Gateway. When you've finished testing a new version, you can just update the alias to point to the updated version instead of updating your API Gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tuning your Resource Configuration
&lt;/h3&gt;

&lt;p&gt;You've probably seen the concept of a GB-second mentioned in the Lambda pricing. Essentially, you get charged based on how long your Lambda function runs, and how many resources you give it; and despite being named a "GB-second", the memory also directly relates to the apportioned CPU and network resources. &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%2Farhc7dv0qgjvfr3vgnbc.jpg" 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%2Farhc7dv0qgjvfr3vgnbc.jpg" alt="Line graph showing the cost of a Lambda function execution given the cost and duration from Lambda Power Tuning" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The more memory you allocate to your function, the faster it works. But the more memory you allocate, your cost also increases. So it's worth finding a sweet spot between memory allocation and function duration. As a general rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you're performing lots of calculations, allocate more memory&lt;/li&gt;
&lt;li&gt;If you're waiting on external calls, allocate less memory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AWS Documentation's &lt;a href="https://docs.aws.amazon.com/lambda/latest/operatorguide/computing-power.html" rel="noopener noreferrer"&gt;Memory and Computing Power&lt;/a&gt; page is a good starting point. To avoid configuring it manually, it's worth checking out &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning" rel="noopener noreferrer"&gt;AWS Lambda Power Tuning&lt;/a&gt;, which will help you find the sweet spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  5) Architecting for serverless
&lt;/h2&gt;

&lt;p&gt;By this point, your AWS Lambda skills have matured enormously. But there's still much to learn in the world of serverless computing. There are a lot of places to get started, so I'd suggest checking out some of these awesome videos from AWS re:Invent 2022&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=-WYBOuP1Y6E" rel="noopener noreferrer"&gt;Get started building your first serverless, event-driven application (SVS209)&lt;/a&gt; by Emily Shea&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=SbL3a9YOW7s" rel="noopener noreferrer"&gt;Building next-gen applications with event-driven architectures (API311-R)&lt;/a&gt; by Eric Johnson&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=qs0U0LdNkV0" rel="noopener noreferrer"&gt;Building Serverlesspresso: Creating event-driven architectures (SVS312)&lt;/a&gt; by James Beswick&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These give you a much deeper exposure to the development and architecture of serverless solutions. Since you already know Lambda, it's far less about the code, and more about the patterns and architectures.&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%2F905w1rho6jaydn99ycgb.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%2F905w1rho6jaydn99ycgb.png" alt="Hiker reaching the top of a mountain seeing the large expanse of valley still ahead" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping-up
&lt;/h2&gt;

&lt;p&gt;The learning with Lambda does not stop here. There are still many areas of the service and development to be further explored! You can find answers to almost any problem between the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/welcome.html" rel="noopener noreferrer"&gt;Developers Guide&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/lambda/latest/operatorguide/intro.html" rel="noopener noreferrer"&gt;Operators Guide&lt;/a&gt;. AWS has made it truly possible to become an expert at their services by being able to navigate their documentation, and Lambda is no exception.&lt;/p&gt;

&lt;p&gt;To dive deeper, check out some of the fantastic content on the &lt;a href="https://www.youtube.com/@AWSEventsChannel" rel="noopener noreferrer"&gt;AWS Events YouTube Channel&lt;/a&gt;, with dozens of incredible talks from re:Invent across all serverless topics. You don't need to spend thousands of dollars to learn from industry leaders, and they are truly worth exploring.&lt;/p&gt;

&lt;p&gt;Lastly, check out more of the content published by members of the AWS Community! You can bet that whatever you're building, someone has done something similar before.&lt;/p&gt;

&lt;p&gt;Keep safe, and happy clouding!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>AWS Melbourne Region - Launch Analysis</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Tue, 24 Jan 2023 00:46:20 +0000</pubDate>
      <link>https://dev.to/aws-builders/aws-melbourne-region-launch-analysis-9mi</link>
      <guid>https://dev.to/aws-builders/aws-melbourne-region-launch-analysis-9mi</guid>
      <description>&lt;p&gt;Local AWS Melbournians woke up to some exciting news today with the long awaited launch of the new AWS Melbourne Region (&lt;code&gt;ap-southeast-4&lt;/code&gt;)!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/aws/now-open-aws-asia-pacific-melbourne-region-in-australia/" rel="noopener noreferrer"&gt;The official announcement&lt;/a&gt; has lots of general information, so I'm going to focus in on some of the more technical implications for builders.&lt;/p&gt;

&lt;p&gt;Special credit to AWS Melbourne User Group Leader &lt;a href="https://www.linkedin.com/in/arjenschwarz" rel="noopener noreferrer"&gt;Arjen Schwarz&lt;/a&gt; who picked up on it &lt;a href="https://www.linkedin.com/posts/aws-user-group-melbourne_aws-reinvent2022-activity-7023390828580519936-8xER/" rel="noopener noreferrer"&gt;a few hours before the official announcement&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Grab your fancy latte, and let's get started ☕&lt;/p&gt;

&lt;h2&gt;
  
  
  👍 Benefits of a New Region
&lt;/h2&gt;

&lt;p&gt;Using new regions requires a lot of work. Beyond simply &lt;a href="https://docs.aws.amazon.com/general/latest/gr/rande-manage.html" rel="noopener noreferrer"&gt;enabling the new region&lt;/a&gt;, we need to extend our architectures, deploy our infrastructure, and do a lot of testing before bringing a new region to production.&lt;/p&gt;

&lt;p&gt;So, what's the upside? Well, there are two major ones:&lt;/p&gt;

&lt;h4&gt;
  
  
  🏃‍♂️ 1) Performance
&lt;/h4&gt;

&lt;p&gt;We want our services to be as close to our customers as possible to enable better performance. When new regions (or &lt;a href="https://aws.amazon.com/about-aws/global-infrastructure/localzones/" rel="noopener noreferrer"&gt;local zones&lt;/a&gt;) come online, we leverage them to achieve single-digit latency.&lt;/p&gt;

&lt;p&gt;After first discovering the S3 endpoint coming online back in November 2022 (they bring the DNS records online early), I'd started to run some simple ping tests from my home in Melbourne to get a general idea of latency. This is the result (dumping to a text file meant no date numbers for the X-axis - oops!):&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%2Fyucu8eab02076tg7ae65.jpg" 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%2Fyucu8eab02076tg7ae65.jpg" alt="Chart" width="800" height="326"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have a significant customer base in Melbourne, especially for latency-sensitive applications, this is very useful. We have had &lt;a href="https://aws.amazon.com/cloudfront/features/#Global_Edge_Network" rel="noopener noreferrer"&gt;Edge Locations&lt;/a&gt; in Melbourne for a while, so if you're using solutions like CloudFront or Lambda@Edge, this doesn't change much.&lt;/p&gt;

&lt;h4&gt;
  
  
  💪 2) Resilience
&lt;/h4&gt;

&lt;p&gt;Multi-regional architecture is a big selling point for the cloud. We can deploy our solutions to be way more resilient, building across large geographical areas and minimizing the effect of major outages.&lt;/p&gt;

&lt;p&gt;Data Sovereignty and other requirements usually mean we need to keep our data in a single country, or group of countries. For Australia, Microsoft Azure has had &lt;a href="https://azure.microsoft.com/en-us/explore/global-infrastructure/geographies/" rel="noopener noreferrer"&gt;multiple local regions&lt;/a&gt; for nearly a decade. This has given Microsoft a significant advantage in Australia for companies that really crave this resilience.&lt;/p&gt;

&lt;p&gt;Architecting for multi-region resilience isn't easy though, and it requires effort to get right, and comes with additional costs. But if you're needing that additional assurance, it's worth checking out. The recently released &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/aws-multi-region-fundamentals/aws-multi-region-fundamentals.html" rel="noopener noreferrer"&gt;AWS Multi-Region Fundamentals Whitepaper&lt;/a&gt; is an excellent resource to get started.&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%2Fmsbnu3585t37ictdc48l.jpg" 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%2Fmsbnu3585t37ictdc48l.jpg" alt="Image description" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ☑ Service Availability
&lt;/h2&gt;

&lt;p&gt;New regions always start out with a smaller subset of services, before adding additional support over time.&lt;/p&gt;

&lt;p&gt;As of launch, AWS has 47 services running in the new Melbourne region. This compares with 194 in Sydney (&lt;code&gt;ap-southeast-2&lt;/code&gt;). All of the standard services you'd expect are there, with &lt;a href="https://aws.amazon.com/ec2/" rel="noopener noreferrer"&gt;EC2&lt;/a&gt;, &lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;Lambda&lt;/a&gt;, &lt;a href="https://aws.amazon.com/s3/" rel="noopener noreferrer"&gt;S3&lt;/a&gt;, &lt;a href="https://aws.amazon.com/dynamodb/" rel="noopener noreferrer"&gt;DynamoDB&lt;/a&gt;, and the like. But there's many services still missing. Here's a short list of some key ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/amplify/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/backup/" rel="noopener noreferrer"&gt;AWS Backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/guardduty/" rel="noopener noreferrer"&gt;Amazon GuardDuty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/sagemaker/" rel="noopener noreferrer"&gt;Amazon SageMaker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/storage-gateway/" rel="noopener noreferrer"&gt;AWS Storage Gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/transit-gateway/" rel="noopener noreferrer"&gt;AWS Transit Gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/workspaces/" rel="noopener noreferrer"&gt;Amazon WorkSpaces&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some services also aren't fully featured yet, like AWS Lambda lacking support for the &lt;code&gt;arm64&lt;/code&gt; architecture &lt;a href="https://aws.amazon.com/blogs/aws/aws-lambda-functions-powered-by-aws-graviton2-processor-run-your-functions-on-arm-and-get-up-to-34-better-price-performance/" rel="noopener noreferrer"&gt;powered by Graviton&lt;/a&gt; yet.&lt;/p&gt;

&lt;p&gt;If you're extending your solutions from another region like Sydney, this might not be a problem. But the current lack of some services like Transit Gateway may slow down many customers looking to extend their operations across the regional divide.&lt;/p&gt;

&lt;p&gt;For the full comparison of supported services at time of launch check out my &lt;a href="https://docs.google.com/spreadsheets/d/1gZOJA9ZbmBfRLPSVEY4iXVziyBVx_zVzUUJBMlUTdsc/edit?usp=sharing" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Sheet&lt;/strong&gt;&lt;/a&gt; for more information.&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%2F1ue80lfmucjmlc7cquex.jpg" 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%2F1ue80lfmucjmlc7cquex.jpg" alt="Photo of a rack mounted server in a datacentre" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🖥 Instance Family Availability
&lt;/h2&gt;

&lt;p&gt;As with services, so too with Instance types. Having a newer region means we're dealing exclusively with newer hardware, so you may not have access to the same instance types as you're expected.&lt;/p&gt;

&lt;p&gt;Obviously we're not getting our beloved &lt;code&gt;t2.micro&lt;/code&gt;'s back (😥), but this is an opportunity to update to the latest instance (and usually cheaper) types as well. Given the list, most types of workloads can be accommodated. Though, there's a few omissions.&lt;/p&gt;

&lt;p&gt;The biggest gap I notice is there's currently no GPU-powered &lt;a href="https://aws.amazon.com/ec2/instance-types/#Accelerated_Computing" rel="noopener noreferrer"&gt;Accelerated Computing&lt;/a&gt; instances available. Aside from the &lt;code&gt;m6gd&lt;/code&gt; family, we also don't have many Graviton-powered instances yet (explaining the situation with Lambda).&lt;/p&gt;

&lt;p&gt;The AWS Management Console will only show you what's available, so don't worry too much there. But if you're deploying solutions with an IaC solution, keep an eye out for any weird deployment bugs with your compute solutions where the instance family may need to be changed.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://docs.google.com/spreadsheets/d/1gZOJA9ZbmBfRLPSVEY4iXVziyBVx_zVzUUJBMlUTdsc/edit?usp=sharing" rel="noopener noreferrer"&gt;&lt;strong&gt;Google Sheet&lt;/strong&gt;&lt;/a&gt; also contains a list of the all of the supported instances compared against the Sydney region.&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%2Fgzcz0wrzub5jehnjhhzs.jpg" 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%2Fgzcz0wrzub5jehnjhhzs.jpg" alt="Image description" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🎉 Conclusion
&lt;/h2&gt;

&lt;p&gt;One thing should be clear: The launch of the Melbourne Region is a really good thing. There are some gaps, but that's because it's a new region, and these things take time to roll out.&lt;/p&gt;

&lt;p&gt;Keep an eye on the AWS news as they announce the new releases; it'll pick up pace now that the region is online. Start your planning now, and you can take advantage of these new capabilities once they're available.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>GPT-Powered chatbot over the phone - Try it, and see how it was built</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Fri, 23 Dec 2022 07:18:21 +0000</pubDate>
      <link>https://dev.to/aws-builders/gpt-powered-chatbot-over-the-phone-try-it-and-see-how-it-was-built-33n9</link>
      <guid>https://dev.to/aws-builders/gpt-powered-chatbot-over-the-phone-try-it-and-see-how-it-was-built-33n9</guid>
      <description>&lt;p&gt;ChatGPT has sent the internet into a frenzy. For developers, it's just the tip of the iceberg. OpenAI's API allows us to leverage the power of the GPT Models in as many ways as we can imagine.&lt;/p&gt;

&lt;p&gt;Today, I hacked together a cutting-edge AI chatbot that you can call from any phone, anywhere in the world. What's more, &lt;strong&gt;you can try it yourself!&lt;/strong&gt; See the end of the article for more details.&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%2Fex1es87v4go9awv39ch1.jpg" 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%2Fex1es87v4go9awv39ch1.jpg" alt="Architecture Diagram of the connectGPT project as explained below" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🗺 Architecture
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/connect/" rel="noopener noreferrer"&gt;Amazon Connect&lt;/a&gt; is a powerful solution that lets us set up a phone number, build contact flows, support call centre agents, and everything in-between. It's not exactly a leader in this space, but it's smooth integration with other AWS Services makes it a breeze for this scenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/lex/" rel="noopener noreferrer"&gt;Amazon Lex&lt;/a&gt;, AWS's natural language conversational AI service. With Amazon Connect, it seamlessly leverages &lt;a href="https://aws.amazon.com/transcribe/" rel="noopener noreferrer"&gt;Amazon Transcribe&lt;/a&gt; to understand what is being said (speech-to-text), and &lt;a href="https://aws.amazon.com/polly/" rel="noopener noreferrer"&gt;Amazon Polly&lt;/a&gt; to provide the verbal response (text-to-speech). We aren't really using the Natural Language powers of Lex, but it has other uses for us:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt; handles the call to OpenAI's API. The function itself is quite simple, although the supporting Lambda Layer was significantly larger. Since OpenAI's API costs money, I've leveraged &lt;a href="https://aws.amazon.com/secrets-manager/" rel="noopener noreferrer"&gt;AWS Secrets Manager&lt;/a&gt; to keep my API Key secure. To make debugging less nightmarish (we'll see why!), &lt;a href="https://aws.amazon.com/cloudwatch/" rel="noopener noreferrer"&gt;Amazon CloudWatch&lt;/a&gt; provides a simple way to store my basic log files, and &lt;a href="https://aws.amazon.com/api-gateway/" rel="noopener noreferrer"&gt;Amazon API Gateway&lt;/a&gt; gives an ability to retrieve them!&lt;/p&gt;

&lt;h2&gt;
  
  
  🛠 Deep Dive into Services
&lt;/h2&gt;

&lt;p&gt;Knowing the architecture is great, but it doesn't help build everything out in detail. Let's dive into some of those services in some more depth:&lt;/p&gt;

&lt;h3&gt;
  
  
  ☎️ Amazon Connect
&lt;/h3&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%2Froekifh9hxor5l3cowdk.jpg" 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%2Froekifh9hxor5l3cowdk.jpg" alt="Contact Flow Diagram in Amazon Connect" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Connect is a powerful service, but it can feel counter-intuitive if you've never managed a virtual contact centre before (lucky you!). Like Quicksight and a few other services, Amazon Connect has its own control panels outside the AWS Management Console.&lt;/p&gt;

&lt;p&gt;First, you need to &lt;a href="https://docs.aws.amazon.com/connect/latest/adminguide/amazon-connect-instances.html" rel="noopener noreferrer"&gt;setup your Amazon Connect instance&lt;/a&gt; in your chosen region. You'll need to &lt;a href="https://docs.aws.amazon.com/connect/latest/adminguide/contact-center-phone-number.html" rel="noopener noreferrer"&gt;setup a DID number&lt;/a&gt; (Direct In-dial number; fancy word for your inbound phone number) for a country of your choice, but make sure it's available in your region on the &lt;a href="https://aws.amazon.com/connect/pricing/" rel="noopener noreferrer"&gt;Connect Pricing page&lt;/a&gt;, and that you meet any necessary regulations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/connect/latest/adminguide/create-contact-flow.html" rel="noopener noreferrer"&gt;Building your Contact Flow&lt;/a&gt; is the cool stuff happens. You can use the editor to build out a workflow that meets your needs in a huge number of works, including logic, prompts, and an ability to trigger Lambda functions, making it hugely extensible!&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%2F264soby1fy1v8nn99fpl.jpg" 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%2F264soby1fy1v8nn99fpl.jpg" alt="Amazon Lex UI showing the bot used by this project" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  💬 Amazon Lex
&lt;/h3&gt;

&lt;p&gt;Lex (v2) is an immensely powerful service for building natural language experiences. The name isn't a coincidence either, since it also powers Amazon Alexa. But we aren't using any of those features; it's just a convenient way of handling the processing between text and speech with our Lambda function! Lex developers, look away now!&lt;/p&gt;

&lt;p&gt;After we &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/build-create.html" rel="noopener noreferrer"&gt;create our bot&lt;/a&gt;, we need to configure it. Normally we would create multiple &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/how-it-works.html" rel="noopener noreferrer"&gt;intents&lt;/a&gt;, with their respective &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/how-it-works.html" rel="noopener noreferrer"&gt;utterances&lt;/a&gt;. Instead, I &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/build-intents.html" rel="noopener noreferrer"&gt;create a single intent&lt;/a&gt; (I called it &lt;code&gt;campingInTents&lt;/code&gt;, because childish humour) with a random utterance (&lt;code&gt;pancakes&lt;/code&gt;; I was hungry). Neither mattered in this case, since both the created intent and the &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/built-in-intent-fallback.html" rel="noopener noreferrer"&gt;default FallbackIntent&lt;/a&gt; are going to be doing the same thing.&lt;/p&gt;

&lt;p&gt;After enabling the &lt;a href="https://docs.aws.amazon.com/lexv2/latest/dg/lambda.html" rel="noopener noreferrer"&gt;Lambda code hooks for initialization&lt;/a&gt;, and configuring the bot to use my Lambda function, it will always behave the same, sending the message through to OpenAI, regardless of what's been said. This is an incredibly hacky way of doing it, and I'm sure there are many better ways. But I'm a hacky dev, building a hacky solution today.&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%2F7lr66s0yh0riqo4roogk.jpg" 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%2F7lr66s0yh0riqo4roogk.jpg" alt="Screenshot of AWS Lambda" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🧠 AWS Lambda
&lt;/h3&gt;

&lt;p&gt;Lambda functions are best when kept simple. This one sends the request to OpenAI, outputs some information for logging, and passes the information back to Lex. More info about the code down below.&lt;/p&gt;

&lt;p&gt;Since it relies on an external API call, it does take a while to execute (&lt;code&gt;1.285 seconds&lt;/code&gt; on average), which is very inefficient, and despite throwing &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning" rel="noopener noreferrer"&gt;Lambda Power Tuning&lt;/a&gt; at the problem, it's purely an external dependency issue, and can't be resolved by resources. You could make it more cost-effective using &lt;a href="https://aws.amazon.com/step-functions/" rel="noopener noreferrer"&gt;AWS Step Functions&lt;/a&gt; to handle the OpenAI API call asyncrhonously, but I didn't worry for this project.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/openai/openai-python" rel="noopener noreferrer"&gt;openai-python library&lt;/a&gt; makes interacting with the API a breeze. Although at 112MB fully installed, including &lt;code&gt;requests&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt;, and &lt;code&gt;pandas&lt;/code&gt;, it's pretty beefy. Consolidating it into a &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html" rel="noopener noreferrer"&gt;Lambda Layer&lt;/a&gt; made it simple and easy to manage. &lt;code&gt;numpy&lt;/code&gt; didn't appreciate running in Lambda after being loaded for my Windows machine, so you may need to &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/lambda-python-package-compatible/" rel="noopener noreferrer"&gt;specify the right package&lt;/a&gt; before building the layer.&lt;/p&gt;

&lt;p&gt;After some incredibly nonsensical replies to my queries, I added some basic logging which is output to CloudWatch logs. The reason is that Amazon Transcribe is &lt;del&gt;awful&lt;/del&gt; still leaving a lot to be desired, especially with my accent. So, I wanted to capture what Transcribe &lt;em&gt;thought&lt;/em&gt; I'd said, leading to some interesting insights. This has to be my favourite:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What I said:&lt;/strong&gt;&lt;br&gt;
What's the key difference between Alexander the Great, and Julius Caesar?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenAI's Response:&lt;/strong&gt;&lt;br&gt;
The key difference between Alexander the Great and Reseda is that Alexander the Great was a Macedonian king and conqueror who reigned from 336-323 BC, while Reseda is a city in Los Angeles, California.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Transcribe thought I said:&lt;/strong&gt;&lt;br&gt;
What's the key difference between alexander great enjoy reseda&lt;/p&gt;
&lt;/blockquote&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%2Fcghboh1zlqqcvrbui6v0.jpg" 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%2Fcghboh1zlqqcvrbui6v0.jpg" alt="Image description" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏱ How much coding?
&lt;/h2&gt;

&lt;p&gt;For a fully-fledged chatbot which comes close to passing the Turing Test, powered by some of the most incredible AI models in the modern age, that runs on the worlds most ubiquitous communication medium, surely there'd be some pretty significant coding required.&lt;/p&gt;

&lt;p&gt;Just 49 lines of code. That's all of the Python code, including comments, which I had to write for Lambda to make this work, &lt;a href="https://github.com/ssennettau/connectGPT/blob/main/connectGPT.py" rel="noopener noreferrer"&gt;all available on GitHub&lt;/a&gt;. Everything else was configuring the existing services. In fact, it can be &lt;a href="https://github.com/ssennettau/connectGPT/blob/main/connectGPT-mini.py" rel="noopener noreferrer"&gt;compacted down into less than 10 lines of code&lt;/a&gt;, though substantially harder to read.&lt;/p&gt;

&lt;p&gt;Modern solutions built around cloud computing, microservices, and API's means you can leverage a surprising amount of power by simply tying solutions together. Reading the code, there's virtually no custom logic involved, except for the prompt. Everything else is arguably just glue code.&lt;/p&gt;

&lt;p&gt;On the pricing dimension, it costs all of &lt;strong&gt;9.7 cents per invocation&lt;/strong&gt;, which is pretty impressive.&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%2Fe9higmbaupibi598ete9.jpg" 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%2Fe9higmbaupibi598ete9.jpg" alt="Photo of a person holding a phone" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  📞 Try it for yourself!
&lt;/h2&gt;

&lt;p&gt;Here we go, the US phone number that hosts the chatbot. OpenAI is expensive, so this will disappear eventually when either it runs out of credits, or gets excessively misused. Give it a try, but be reasonable!&lt;/p&gt;

&lt;p&gt;&lt;del&gt;&lt;strong&gt;+1 (445) 202-5802&lt;/strong&gt;&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update: Number has now been taken down&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It does take several seconds for the API to return the response, so don't be surprised if it takes a little while.&lt;/p&gt;

&lt;p&gt;Stay safe over the holiday season, and best wishes towards 2023!&lt;/p&gt;

</description>
      <category>writing</category>
      <category>motivation</category>
    </item>
    <item>
      <title>Troubleshooting AWS Application Composer Errors</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Wed, 21 Dec 2022 02:29:27 +0000</pubDate>
      <link>https://dev.to/aws-builders/troubleshooting-aws-application-composer-errors-445a</link>
      <guid>https://dev.to/aws-builders/troubleshooting-aws-application-composer-errors-445a</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;a href="https://aws.amazon.com/application-composer/" rel="noopener noreferrer"&gt;AWS Application Composer&lt;/a&gt;&lt;/strong&gt; was released to &lt;a href="https://aws.amazon.com/blogs/compute/visualize-and-create-your-serverless-workloads-with-aws-application-composer/" rel="noopener noreferrer"&gt;Public Preview during re:Invent 2022&lt;/a&gt;. The &lt;a href="https://docs.aws.amazon.com/application-composer/latest/dg/what-is-composer.html" rel="noopener noreferrer"&gt;Developer Guide Documentation&lt;/a&gt; covers the basics of how to use the service, but currently there's limited guidelines on troubleshooting bugs.&lt;/p&gt;

&lt;p&gt;When loading an existing SAM Template, the following error may appear:&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%2F98itfysh1ehdh8411j9s.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%2F98itfysh1ehdh8411j9s.png" alt="Screenshot of the error below" width="523" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Incompatible template&lt;/strong&gt;&lt;br&gt;
An incompatible or malformed template has been detected, which means it is not accessible in Composer. Load another file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The front-end provides no further details, but they are output into the browser console. For this error, the &lt;code&gt;INITIALIZE_PROJECT_FAILED&lt;/code&gt; event offers insight:&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%2F64424ye3wcaz6o23cf9y.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%2F64424ye3wcaz6o23cf9y.png" alt="Screenshot of a JSON event in the browser console" width="771" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My error appeared to be related to the concurrent release of &lt;a href="https://aws.amazon.com/blogs/aws/step-functions-distributed-map-a-serverless-solution-for-large-scale-parallel-data-processing/" rel="noopener noreferrer"&gt;Step Functions Distributed Map&lt;/a&gt;, which changed some language definition in ASL around the &lt;code&gt;Map&lt;/code&gt; state, and may not yet be reflected in App Composer's validator.&lt;/p&gt;

&lt;p&gt;AWS Application Composer is still in Preview, which means it's still undergoing active development, and things constantly shift about in AWS. If you find a similar error, it's worth sending feedback to the Service Team using the link in the AWS Console.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>AWS Serverless Badge: Value and Potential for Cloud Professionals</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Sat, 10 Dec 2022 04:43:39 +0000</pubDate>
      <link>https://dev.to/ssennettau/aws-serverless-badge-value-and-potential-for-cloud-professionals-564e</link>
      <guid>https://dev.to/ssennettau/aws-serverless-badge-value-and-potential-for-cloud-professionals-564e</guid>
      <description>&lt;p&gt;During re:Invent 2022, AWS announced the release of their new &lt;a href="https://aws.amazon.com/blogs/compute/introducing-new-aws-serverless-digital-learning-badges/" rel="noopener noreferrer"&gt;AWS Serverless digital learning badges&lt;/a&gt;. For context, Digital Badges are issued as part of the &lt;a href="https://explore.skillbuilder.aws/learn" rel="noopener noreferrer"&gt;AWS Skill Builder&lt;/a&gt; platform as part of completing an assessment at the end of a learning path. Similar concept to certifications, except that they're free to attempt, and aren't proctored.&lt;/p&gt;

&lt;p&gt;Having experience with serverless tech and having previously written about the need for an AWS Serverless-oriented certification, I sat the assessment, and now it's time to share my thoughts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;The badge comes as part of the &lt;a href="https://explore.skillbuilder.aws/learn/public/learning_plan/view/92/serverless-learning-plan" rel="noopener noreferrer"&gt;Skill Builder Serverless Learning Plan&lt;/a&gt;, where you can either start at the beginning with the courses, or jump straight ahead to the &lt;strong&gt;Serverless Learning Plan Badge Assessment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The assessment has 50 questions, and no time limit. Score to pass is 80% (40 questions correct), with a one-day waiting period to retake the assessment if you fail an attempt. Upon passing, you'll receive a link to your &lt;a href="https://www.credly.com/earner/earned/badge/637435e4-93d9-4b9a-8fd8-a389a37ec731" rel="noopener noreferrer"&gt;Credly badge&lt;/a&gt; within up to five days, but in my experience, it's usually within one business day.&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%2Feg9wx0ckm0pkzawh63f1.jpg" 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%2Feg9wx0ckm0pkzawh63f1.jpg" alt="Image" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Difficulty
&lt;/h2&gt;

&lt;p&gt;The difficulty level would be similar to an &lt;strong&gt;Associate-level&lt;/strong&gt; ceritifcation, with substantial overlap with the &lt;a href="https://aws.amazon.com/certification/certified-developer-associate/" rel="noopener noreferrer"&gt;AWS Certified Developer Associate certification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Learning Path seems to cover all of the topics you'd need to pass the assessment, so even if you don't know all the answers yet, you can find them between the courses and the AWS Documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Badges vs Certifications
&lt;/h2&gt;

&lt;p&gt;The main difference between a Digital Badge and a Certification is that the assessments for Badges are not proctored. Where a Certification Exam must be taken within a controlled environment, like at a testing centre, or &lt;a href="https://acloudguru.com/blog/engineering/my-near-disaster-aws-solutions-architect-professional-recertification-experience" rel="noopener noreferrer"&gt;under very strict conditions at home&lt;/a&gt;, the assessments for Badges can be undertaken in your web browser, without restrictions or time limits.&lt;/p&gt;

&lt;p&gt;Since there's no restrictions, the candidate can research any answers for the Digital Badge assessment, like an open book exam. This means the candidate doesn't need to prove their knowledge in the same way as with a certification exam.&lt;/p&gt;

&lt;p&gt;Being able to reference documentation is a critical timely skill. But that doesn't count if and when brain dumps of the assessment begin appearing online, and people use them to bypass the need for knowledge entirely.&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%2Fcfzj56zt49zsm1i23p4y.jpg" 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%2Fcfzj56zt49zsm1i23p4y.jpg" alt="Image" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Worth it?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It's a great starting point both as a personal benchmark for your own knowledge, and a means to show employers that you're deeply interested in serverless technology.&lt;/strong&gt; For Hiring Managers, take it as a good sign that there's a baseline level of knowledge, and that the candidate has been interested enough in the topic to pursue it.&lt;/p&gt;

&lt;p&gt;Digital Badges have been around for nearly a year, with the first ones being released in &lt;a href="https://aws.amazon.com/blogs/aws/demonstrate-your-aws-cloud-storage-knowledge-and-skills-with-new-digital-badges/" rel="noopener noreferrer"&gt;February 2022&lt;/a&gt;. More people are taking them up, but it's still slow going, and with a limited range of topics. I believe the Serverless Digital Badge is the first one that will see more consistent adoption.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Have you sat the AWS Serverless Badge assessment? What were you impressions?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Viewing Cost Explorer Usage with AWS Credits</title>
      <dc:creator>Stephen Sennett</dc:creator>
      <pubDate>Tue, 21 Dec 2021 08:54:41 +0000</pubDate>
      <link>https://dev.to/aws-builders/viewing-cost-explorer-usage-with-aws-credits-39ko</link>
      <guid>https://dev.to/aws-builders/viewing-cost-explorer-usage-with-aws-credits-39ko</guid>
      <description>&lt;p&gt;When you have &lt;a href="https://aws.amazon.com/awscredits/" rel="noopener noreferrer"&gt;AWS Promotional Credits&lt;/a&gt; applied to your account, by default your usage will be hidden from the Cost Explorer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/aws-cost-management/aws-cost-explorer/" rel="noopener noreferrer"&gt;AWS Cost Explorer&lt;/a&gt; is primarily concerned with showing you what the impact is to your billing &amp;amp; payments. Since Credits have already been applied to your account, you don't need to pay for it in an upcoming invoice.&lt;/p&gt;

&lt;p&gt;Some charges for &lt;em&gt;Ineligible Services&lt;/em&gt; not covered by AWS Promotional Credits may still show up, like Domain Registration,  upfront RI costs, etc. For the rest, you'll need to change the &lt;a href="https://docs.aws.amazon.com/cost-management/latest/userguide/ce-filtering.html" rel="noopener noreferrer"&gt;Cost Explorer filter&lt;/a&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%2F55cookfrh7ho6rxrceow.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%2F55cookfrh7ho6rxrceow.png" alt="Cost Explorer chart showing low usage - $10 in a month at most" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To show all usage in your AWS Account, including those covered by Credits, select the filter on the right-side of the Screen for &lt;strong&gt;Charge Type&lt;/strong&gt;, change it to &lt;strong&gt;Exclude Only&lt;/strong&gt;, and check the box for &lt;strong&gt;Credits&lt;/strong&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%2Fjhsfxe7okqsrgvpibf7s.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%2Fjhsfxe7okqsrgvpibf7s.png" alt="Filter Settings for Excluding Credits" width="429" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once applied, all charges on the account will be visible. Including any that may have been forgotten.&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%2Fku2v2y4v39ihxh95xzog.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%2Fku2v2y4v39ihxh95xzog.png" alt="Cost Explorer chart showing substantially higher usage, including caption '$250 on a forgotten Aurora Cluster... oops'" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just an alternative education expensive.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
  </channel>
</rss>
