<?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: Tomasz Łakomy</title>
    <description>The latest articles on DEV Community by Tomasz Łakomy (@tlakomy).</description>
    <link>https://dev.to/tlakomy</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%2F146754%2F1e100745-01e4-48d6-bb53-f1461b2af5ba.jpg</url>
      <title>DEV Community: Tomasz Łakomy</title>
      <link>https://dev.to/tlakomy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tlakomy"/>
    <language>en</language>
    <item>
      <title>Quick guide to CSS Grid</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Wed, 27 Dec 2023 18:29:12 +0000</pubDate>
      <link>https://dev.to/tlakomy/quick-guide-to-css-grid-1b95</link>
      <guid>https://dev.to/tlakomy/quick-guide-to-css-grid-1b95</guid>
      <description>&lt;h2&gt;
  
  
  Grid Container
&lt;/h2&gt;

&lt;p&gt;First, you designate an element as a grid container. This element will hold the grid items (your content). You can do this by setting the element's display property to &lt;code&gt;grid&lt;/code&gt; or &lt;code&gt;inline-grid&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* Or for an inline grid */&lt;/span&gt;
&lt;span class="nc"&gt;.inline-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;inline-grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining Rows and Columns
&lt;/h2&gt;

&lt;p&gt;You define the rows and columns in the grid container using &lt;code&gt;grid-template-rows&lt;/code&gt; and &lt;code&gt;grid-template-columns&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt; &lt;span class="m"&gt;200px&lt;/span&gt; &lt;span class="nb"&gt;auto&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-rows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grid Gap
&lt;/h2&gt;

&lt;p&gt;Grid gap is the space between each row and column. Use &lt;code&gt;grid-gap&lt;/code&gt;, &lt;code&gt;grid-row-gap&lt;/code&gt;, and &lt;code&gt;grid-column-gap&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-gap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Space between rows and columns */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Placing Items
&lt;/h2&gt;

&lt;p&gt;You can place grid items in specific locations using &lt;code&gt;grid-column-start&lt;/code&gt;, &lt;code&gt;grid-column-end&lt;/code&gt;, &lt;code&gt;grid-row-start&lt;/code&gt;, and &lt;code&gt;grid-row-end&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-column-start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-column-end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-row-start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-row-end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Shorthand Properties
&lt;/h2&gt;

&lt;p&gt;There are shorthand properties for quicker definitions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;grid-column&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Start at line 1 and end at line 3 */&lt;/span&gt;
  &lt;span class="nl"&gt;grid-row&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Fractional Units (fr)
&lt;/h2&gt;

&lt;p&gt;The fr unit allows you to distribute available space in fractions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* 2nd column is twice as wide as the others */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Repeat Function
&lt;/h2&gt;

&lt;p&gt;To avoid repetition, use &lt;code&gt;repeat()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* Creates 3 columns of equal width */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  auto-fill and auto-fit
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;auto-fill&lt;/code&gt; and &lt;code&gt;auto-fit&lt;/code&gt; are used with repeat() to automatically place as many items as possible.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.container {
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Grid Areas
&lt;/h2&gt;

&lt;p&gt;Define areas in your grid and assign items to these areas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-areas&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
    &lt;span class="s1"&gt;"header header header"&lt;/span&gt;
    &lt;span class="s1"&gt;"sidebar content content"&lt;/span&gt;
    &lt;span class="s1"&gt;"footer footer footer"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.header&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Responsive Design
&lt;/h2&gt;

&lt;p&gt;You can create responsive designs by combining CSS Grid with media queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="py"&gt;grid-template-columns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="n"&gt;fr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Practice
&lt;/h2&gt;

&lt;p&gt;The best way to learn CSS Grid is through practice. Try creating a basic layout with a header, sidebar, main content area, and footer. Experiment with different configurations and see how the elements rearrange themselves.&lt;/p&gt;

</description>
      <category>css</category>
      <category>grid</category>
    </item>
    <item>
      <title>CloudFront Functions vs. Lambda@Edge: what's the difference?</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Wed, 22 Nov 2023 11:34:01 +0000</pubDate>
      <link>https://dev.to/aws-heroes/cloudfront-functions-vs-lambdaedge-whats-the-difference-1g60</link>
      <guid>https://dev.to/aws-heroes/cloudfront-functions-vs-lambdaedge-whats-the-difference-1g60</guid>
      <description>&lt;p&gt;AWS announced &lt;a href="https://aws.amazon.com/blogs/aws/introducing-amazon-cloudfront-keyvaluestore-a-low-latency-datastore-for-cloudfront-functions/"&gt;CloudFront KeyValueStore&lt;/a&gt; yesterday which enhances the capabilities of CloudFront Functions. In case you're not familiar, here's a quick summary of what CloudFront Functions do:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Amazon CloudFront allows you to securely deliver static and dynamic content with low latency and high transfer speeds. With CloudFront Functions, you can perform latency-sensitive customizations for millions of requests per second. For example, you can use CloudFront Functions to modify headers, normalize cache keys, rewrite URLs, or authorize requests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You may also be familiar with &lt;a href="https://aws.amazon.com/lambda/edge/"&gt;Lambda@Edge&lt;/a&gt; which is a similar service that allows you to run Lambda functions at the edge of the AWS network. To quote the AWS docs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Lambda@Edge is a feature of Amazon CloudFront that lets you run code closer to users of your application, which improves performance and reduces latency. With Lambda@Edge, you don't have to provision or manage infrastructure in multiple locations around the world. You pay only for the compute time you consume - there is no charge when your code is not running.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading those two descriptions you may be wondering - what's the difference between those two services? Let's take a look!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Programming language:&lt;/strong&gt; Lambda@Edge supports Node.js and Python. CloudFront Functions support JavaScript only. Not really a problem for me personally (I'm a JavaScript developer) but it's worth mentioning.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execution Location:&lt;/strong&gt; Lambda@Edge functions are executed in 13 CloudFront Regional Edge Caches, whereas CloudFront Functions are executed in 225+ CloudFront Edge Locations. This means that CloudFront Functions are may be executed closer to the end user, which means lower latency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Trigger points
&lt;/h2&gt;

&lt;p&gt;CloudFront Functions can be triggered by the following events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When CloudFront receives a request from a viewer (viewer request)&lt;/li&gt;
&lt;li&gt;Before CloudFront returns the response to the viewer (viewer response)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-add-triggers.html"&gt;Lambda@Edge function can be triggered&lt;/a&gt; when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CloudFront receives a request from a viewer (viewer request)&lt;/li&gt;
&lt;li&gt;Before CloudFront returns the response to the viewer (viewer response)&lt;/li&gt;
&lt;li&gt;CloudFront forwards a request to your origin (origin request)&lt;/li&gt;
&lt;li&gt;After CloudFront receives the response from the origin and before it caches the object in the response (origin response)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maximum execution time&lt;/strong&gt;: CloudFront Functions need to finish under a millisecond (so if your code is as slow as mine, you should consider using Lambda@Edge). Lambda@Edge functions can run for up to 5 seconds for viewer request and viewer response triggers, and up to 30 seconds for origin request and origin response triggers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Network access&lt;/strong&gt;: CloudFront Functions can't access the network. Lambda@Edge functions can access the network.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;HTTP manipulation&lt;/strong&gt;: CloudFront Functions can only manipulate HTTP headers. If you need to remove or replace the body of an HTTP request or response, use Lambda@Edge instead.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Filesystem access&lt;/strong&gt;: CloudFront Functions don't have access to filesystem (which makes sense, especially given the 1ms limit). Lambda@Edge functions can access the filesystem.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scale&lt;/strong&gt;: CloudFront Functions can scale &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-choosing.html"&gt;to 10,000,000 requests per second or more&lt;/a&gt;. Lambda@Edge functions can scale up to 10,000 requests per second per Region.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory&lt;/strong&gt;: CloudFront Functions have 2MB of memory available. Lambda@Edge functions have 128MB - 3GB of memory available.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maximum function size&lt;/strong&gt;: CloudFront Functions need to be tiny - they can't be larger than 10KB. Lambda@Edge functions can be up to 1MB in size (for viewer request and viewer response triggers) and 50MB in size (for origin request and origin response triggers).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  CloudFront Functions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cache key normalization – You can transform HTTP request attributes (headers, query strings, cookies, and even the URL path) to create an optimal cache key, which can improve your cache hit ratio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Header manipulation – You can insert, modify, or delete HTTP headers in the request or response. For example, you can add a True-Client-IP header to every request.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL redirects or rewrites – You can redirect viewers to other pages based on information in the request, or rewrite all requests from one path to another.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Request authorization – You can validate hashed authorization tokens, such as JSON web tokens (JWT), by inspecting authorization headers or other request metadata.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Lambda@Edge
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Functions that take several milliseconds or more to complete.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functions that require adjustable CPU or memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functions that depend on third-party libraries (including the AWS SDK, for integration with other AWS services).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functions that require network access to use external services for processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Functions that require file system access or access to the body of HTTP requests.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>cloudfront</category>
    </item>
    <item>
      <title>Full Stack TypeScript with AWS Cloud Development Kit v2</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Wed, 22 Nov 2023 08:56:34 +0000</pubDate>
      <link>https://dev.to/tlakomy/full-stack-typescript-with-aws-cloud-development-kit-v2-4e62</link>
      <guid>https://dev.to/tlakomy/full-stack-typescript-with-aws-cloud-development-kit-v2-4e62</guid>
      <description>&lt;p&gt;I've just released my latest course &lt;a href="https://egghead.io/courses/full-stack-typescript-with-aws-cloud-development-kit-v2-2daa5cf1?af=6p5abz"&gt;Full Stack TypeScript with AWS Cloud Development Kit course&lt;/a&gt; for &lt;a href="https://egghead.io/?af=6p5abz"&gt;egghead.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Really excited about this one, in this course you'll learn how to build full stack applications on AWS with only a single programming language - &lt;strong&gt;TypeScript&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's right - frontend, backend &lt;em&gt;and&lt;/em&gt; infrastructure - all provisioned in AWS by nothing more than sheer force of TypeScript (and willpower).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;17 lessons, 47 minutes&lt;/strong&gt; - easily watchable during a lunch break.&lt;/p&gt;

&lt;p&gt;If you are a web developer who has never touched AWS - by all means, give this course a shot. In less than an hour we're going to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating a new CDK app&lt;/li&gt;
&lt;li&gt;building and deploying AWS Lambda functions&lt;/li&gt;
&lt;li&gt;creating an API Gateway&lt;/li&gt;
&lt;li&gt;using DynamoDB&lt;/li&gt;
&lt;li&gt;deploying static sites to AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And much more! &lt;/p&gt;

&lt;p&gt;The best part? We're &lt;em&gt;barely&lt;/em&gt; touching the AWS Console - with CDK we get to build cloud infrastructure using familiar programming languages we love (or at least - tolerate).&lt;/p&gt;

&lt;p&gt;All you need is a little bit of TypeScript to build full stack applications.&lt;/p&gt;

&lt;p&gt;Hope you like it, and have fun learning!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://egghead.io/courses/full-stack-typescript-with-aws-cloud-development-kit-v2-2daa5cf1?af=6p5abz"&gt;Full Stack TypeScript with AWS Cloud Development Kit course&lt;/a&gt; for &lt;a href="https://egghead.io/?af=6p5abz"&gt;egghead.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Overview of AWS Lambda internal extensions</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Thu, 16 Nov 2023 13:23:07 +0000</pubDate>
      <link>https://dev.to/aws-heroes/overview-of-aws-lambda-internal-extensions-2i8p</link>
      <guid>https://dev.to/aws-heroes/overview-of-aws-lambda-internal-extensions-2i8p</guid>
      <description>&lt;p&gt;Before we start - this blogpost is strongly inspired by excellent &lt;a href="https://www.youtube.com/watch?v=vEYffPn4Mtc&amp;amp;list=PLJo-rJlep0ECO8od7NRdfJ4OrnQ7TMAwj"&gt;AWS Lambda extensions: The deep dive&lt;/a&gt; series by &lt;a href="https://twitter.com/julian_wood"&gt;Julian Wood&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are AWS Lambda extensions?
&lt;/h2&gt;

&lt;p&gt;AWS Lambda extensions allow you augement your Lambda functions, for instance to more easily integrate your Lambda functions with your favorite (or the ones you can afford!) third party tools and services for monitoring, observability, security, and governance.&lt;/p&gt;

&lt;p&gt;Lambda supports both internal and external extensions, with a number of differences between the two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;External extensions&lt;/strong&gt; run as an independent process in the execution environment and continue to run after the Lambda function invocation completes. They can be written in any language and can be packaged and deployed as Lambda layers. External exentions can be used to perform tasks such as monitoring, observability, security, and governance. Moreover, they can be used with any Lambda runtime.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Internal extensions&lt;/strong&gt; run within the runtime, in-process with your code as a separate thread. There are two ways an internal extension is accessed by a function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in-process mechanism (such as &lt;code&gt;NODE_OPTIONS&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a wrapper script that customizes the runtime startup behavior of a Lambda function&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Modifying the runtime environment with internal AWS Lambda extensions
&lt;/h2&gt;

&lt;p&gt;Internal extensions allow you to modify the runtime environment of your Lambda functions. This can be done in two ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  Language-specific environment variables
&lt;/h3&gt;

&lt;p&gt;Lambda supports configuration-only ways to enable code to be pre-loaded during function initialization through the following language-specific environment variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;JAVA_TOOL_OPTIONS&lt;/code&gt; - this environment variable allows you to set additional command-line variables in Lambda. For instance you can specify the initialization of tools, specifically the launching of native or Java programming language agents using the agentlib or javaagent options.

&lt;ul&gt;
&lt;li&gt;As an example you can custom garbage collector behavior by setting &lt;code&gt;JAVA_TOOL_OPTIONS&lt;/code&gt; to &lt;code&gt;-XX:+UseParallelGC&lt;/code&gt;. See &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/java-customization.html#java-tool-options"&gt;AWS docs on JAVA_TOOL_OPTIONS&lt;/a&gt; for more details.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NODE_OPTIONS&lt;/code&gt; - Lambda supports this environment variable - all available options would be a bit of an overkill for a blogpost, but you can find all of them in &lt;a href="https://nodejs.org/docs/latest-v20.x/api/cli.html"&gt;Node.js documentation&lt;/a&gt;. 

&lt;ul&gt;
&lt;li&gt;Speaking of documentation - AWS docs say that "On Node.js 10x and above, Lambda supports this environment variable". Which is &lt;em&gt;technically&lt;/em&gt; true but as of this writing the lowest available &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html"&gt;Lambda runtime version of Node.js&lt;/a&gt; is Node.js 14. I took the liberty of sending feedback to AWS to update the docs.&lt;/li&gt;
&lt;li&gt;Side note: &lt;a href="https://aws.amazon.com/about-aws/whats-new/2023/11/aws-lambda-support-node-js-20/"&gt;Node.js 20 Lambda was announced yesterday&lt;/a&gt;!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DOTNET_STARTUP_HOOKS&lt;/code&gt; - to quote the docs: "on .NET Core 3.1 and above, this environment variable specifies a path to an assembly (dll) that Lambda can use.".&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wrapper scripts
&lt;/h3&gt;

&lt;p&gt;You can create a wrapper script to customize the runtime startup behaviour of your Lambda function which allows you to set configuration parameters that cannot be set through language specific environment variables described above.&lt;/p&gt;

&lt;p&gt;Bear in mind that invocations may fail if the wrapper script does not successfully start the runtime process, so tread carefully. Consider not modifying the wrapper script on a Friday.&lt;/p&gt;

&lt;p&gt;When you use a wrapper script for your function, Lambda starts the runtime using your script. Lambda sends to your script the path to the interpreter and all of the original arguments for the standard runtime startup.&lt;/p&gt;

&lt;p&gt;In order to specify the script set the value of &lt;code&gt;AWS_LAMBDA_EXEC_WRAPPER&lt;/code&gt; environment variable to the path of the script. The script must be executable. Here's an example of a wrapper script for Python&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="c1"&gt;#!/bin/bash
&lt;/span&gt;
  &lt;span class="c1"&gt;# the path to the interpreter and all of the originally intended arguments
&lt;/span&gt;  &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"$@"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# the extra options to pass to the interpreter
&lt;/span&gt;  &lt;span class="n"&gt;extra_args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"-X"&lt;/span&gt; &lt;span class="s"&gt;"importtime"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# insert the extra options
&lt;/span&gt;  &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${args[@]:0:$#-1}"&lt;/span&gt; &lt;span class="s"&gt;"${extra_args[@]}"&lt;/span&gt; &lt;span class="s"&gt;"${args[@]: -1}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;# start the runtime with the extra options
&lt;/span&gt;  &lt;span class="k"&gt;exec&lt;/span&gt; &lt;span class="s"&gt;"${args[@]}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;BTW, if you'd like to learn more about AWS Lambda environment variables, consider checking out &lt;a href="https://cloudash.dev/blog/aws-lambda-default-environment-variables"&gt;Guide to default AWS Lambda environment variables&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Creating a safe external HTML link - what's the deal with nofollow / noopener / norefferer ?</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Wed, 08 Nov 2023 07:57:30 +0000</pubDate>
      <link>https://dev.to/tlakomy/creating-a-safe-external-html-link-whats-the-deal-with-nofollow-noopener-norefferer--5a4i</link>
      <guid>https://dev.to/tlakomy/creating-a-safe-external-html-link-whats-the-deal-with-nofollow-noopener-norefferer--5a4i</guid>
      <description>&lt;p&gt;In HTML, when you create a link using the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; element, you can add various attributes to control the behavior of that link. The rel attribute specifically defines the relationship between the current document and the linked document. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;nofollow&lt;/code&gt;: This instructs search engines not to follow the link for crawling purposes. It's often used to signal that the site providing the link does not endorse the linked content. This is important for SEO (Search Engine Optimization) because it tells search engines not to pass along ranking credit to the linked page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;noopener&lt;/code&gt;: This prevents the new page from being able to access the window.opener property and ensures it runs in a separate process. Without this, the new page can potentially redirect your page to a different URL. It's a security feature, particularly important when target="_blank" is used, which opens the link in a new tab or window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;noreferrer&lt;/code&gt;: When a user clicks a link, the browser generally sends an HTTP header called Referer (sic) to the new page, which indicates the URL of the previous page. The noreferrer attribute value prevents the browser from sending this referer header, which enhances privacy by not disclosing the source page's URL. It also has implications similar to noopener with regard to security.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s how you might see these attributes in an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag:&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;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://externalwebsite.com"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"nofollow noopener noreferrer external"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Visit External Website&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;href="https://externalwebsite.com"&lt;/code&gt;: Specifies the URL of the linked document.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rel="nofollow noopener noreferrer"&lt;/code&gt;: Specifies the relationship between the current document and the linked one with the terms explained above.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;target="_blank"&lt;/code&gt;: Opens the linked document in a new window or tab.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>html</category>
    </item>
    <item>
      <title>Use patterns in CloudWatch Logs Insights to investigate production issues faster</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Mon, 16 Oct 2023 10:50:40 +0000</pubDate>
      <link>https://dev.to/aws-heroes/use-patterns-in-cloudwatch-logs-insights-to-investigate-production-issues-faster-3ma4</link>
      <guid>https://dev.to/aws-heroes/use-patterns-in-cloudwatch-logs-insights-to-investigate-production-issues-faster-3ma4</guid>
      <description>&lt;p&gt;Browsing through CloudWatch Logs can be a chore, especially when you're debugging a production issue. Having to sift through thousands (if not more!) log lines can be a daunting task, especially when you're not sure what you're looking for.&lt;/p&gt;

&lt;p&gt;Let's take an example - suppose we're working on a serverless app that uses DynamoDB as a database. We're seeing some errors in our Lambda functions and we want to see if there's anything in the logs that could help us debug the issue.&lt;/p&gt;

&lt;p&gt;Customers reported issues with the logic handled by &lt;code&gt;createUser&lt;/code&gt; function so let's see what's going on by running a basic Logs Insights query:&lt;/p&gt;

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

fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| limit 20


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75pusd9z3khgoaq0yc2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75pusd9z3khgoaq0yc2f.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see - by default we're getting &lt;strong&gt;all&lt;/strong&gt; the logs, including &lt;code&gt;START&lt;/code&gt;, &lt;code&gt;REPORT&lt;/code&gt; and &lt;code&gt;END&lt;/code&gt; entries. While they can be useful in some cases, they're not really helpful in our case. Let's narrow down the search by looking only for &lt;code&gt;error&lt;/code&gt;s.&lt;/p&gt;

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

fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| filter @message like /(?i)error/
| limit 20


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

&lt;/div&gt;

&lt;p&gt;If you're confused about that &lt;code&gt;/(?i)error/&lt;/code&gt; syntax, you may want to check out &lt;a href="https://cloudash.dev/blog/match-case-insensitive-substrings-cloudwatch-logs-insights" rel="noopener noreferrer"&gt;Match case-insensitive patterns when using CloudWatch Logs Insights&lt;/a&gt; article.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkamp9c3j2b673zqxm9h2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkamp9c3j2b673zqxm9h2.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, this is slightly better - we're getting only the logs that contain the word &lt;code&gt;error&lt;/code&gt; in them. Since we applied a &lt;code&gt;limit&lt;/code&gt; command, we're only getting latest 20 entries, which is a lot to go through (especially at 2am).&lt;/p&gt;

&lt;p&gt;When investigating a production issue our goal is to get to the root cause as quickly as possible. We don't want to spend time looking through the logs, we want to find the issue and fix it.&lt;/p&gt;

&lt;p&gt;Here's how the new addition to CloudWatch Logs Insights - &lt;code&gt;pattern&lt;/code&gt; keyword - can help.&lt;/p&gt;

&lt;p&gt;Let's update our query:&lt;/p&gt;

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

fields @timestamp, @message, @logStream, @log
| sort @timestamp desc
| filter @message like /(?i)error/
| pattern @message # this is new!


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

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foedrmqrs6zca7lmjkr8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foedrmqrs6zca7lmjkr8m.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is more like it! Instead of getting tons of &lt;strong&gt;very&lt;/strong&gt; similar log lines, CloudWatch managed to uncover patterns in our &lt;code&gt;@message&lt;/code&gt; field and group them together.&lt;/p&gt;

&lt;p&gt;For instance, a following log entry:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="mi"&gt;2023-10-16&lt;/span&gt;&lt;span class="err"&gt;T&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;50.458&lt;/span&gt;&lt;span class="err"&gt;Z&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;b&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="err"&gt;f&lt;/span&gt;&lt;span class="mi"&gt;908&lt;/span&gt;&lt;span class="err"&gt;e-c&lt;/span&gt;&lt;span class="mi"&gt;884-4803&lt;/span&gt;&lt;span class="err"&gt;-b&lt;/span&gt;&lt;span class="mi"&gt;496-33099&lt;/span&gt;&lt;span class="err"&gt;d&lt;/span&gt;&lt;span class="mi"&gt;173&lt;/span&gt;&lt;span class="err"&gt;f&lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;INFO&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="err"&gt;message:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Error:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;timestamp:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Mon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Oct&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;GMT'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;requestId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;275828&lt;/span&gt;&lt;span class="err"&gt;cf&lt;/span&gt;&lt;span class="mi"&gt;-9315-4&lt;/span&gt;&lt;span class="err"&gt;bbd&lt;/span&gt;&lt;span class="mi"&gt;-8&lt;/span&gt;&lt;span class="err"&gt;de&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="err"&gt;-a&lt;/span&gt;&lt;span class="mi"&gt;40555&lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="err"&gt;fb&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;userId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="err"&gt;cf&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;eb&lt;/span&gt;&lt;span class="mi"&gt;6-96&lt;/span&gt;&lt;span class="err"&gt;fc&lt;/span&gt;&lt;span class="mi"&gt;-4&lt;/span&gt;&lt;span class="err"&gt;da&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;-b&lt;/span&gt;&lt;span class="mi"&gt;135-99e193&lt;/span&gt;&lt;span class="err"&gt;fe&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="err"&gt;ed&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="err"&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;is turned into the following after applying the &lt;code&gt;pattern&lt;/code&gt; keyword:&lt;/p&gt;

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

&amp;lt;*&amp;gt; &amp;lt;*&amp;gt; INFO    {
  message: 'Error: cannot create user',
  timestamp: 'Mon, &amp;lt;*&amp;gt; &amp;lt;*&amp;gt; &amp;lt;*&amp;gt; &amp;lt;*&amp;gt; GMT',
  requestId: &amp;lt;*&amp;gt;,
  userId: &amp;lt;*&amp;gt;
}


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

&lt;/div&gt;

&lt;p&gt;As we can see - the &lt;code&gt;pattern&lt;/code&gt; keyword is able to identify patterns in our log lines and group them together. This is a huge time saver, especially when you're dealing with a lot of logs. We're no longer seeing unrelevant fields like &lt;code&gt;requestId&lt;/code&gt; or &lt;code&gt;userId&lt;/code&gt; - we're only seeing the fields that are relevant to us, such as the error message.&lt;/p&gt;

&lt;p&gt;With that knowledge we're ready to dig into our codebase and fix the issue.&lt;/p&gt;

&lt;p&gt;In the screenshot above you may have noticed other fields such as &lt;code&gt;@ratio&lt;/code&gt;, &lt;code&gt;@sampleCount&lt;/code&gt; and &lt;code&gt;@severityLabel&lt;/code&gt;, let's see what &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax-Pattern.html" rel="noopener noreferrer"&gt;AWS docs&lt;/a&gt; have to say about them:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The pattern command produces the following output:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@pattern&lt;/code&gt;: A shared text structure that recurs among your log event fields. Fields that vary within a pattern, such as a request ID or timestamp, are represented by &lt;code&gt;&amp;lt;*&amp;gt;&lt;/code&gt;. For example, &lt;code&gt;[INFO] Request time: &amp;lt;*&amp;gt;&lt;/code&gt; ms is a potential output for the log message &lt;code&gt;[INFO] Request time: 327 ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@ratio&lt;/code&gt;: The ratio of log events from a selected time period and specified log groups that match an identified pattern. For example, if half of the log events in the selected log groups and time period match the pattern, &lt;code&gt;@ratio&lt;/code&gt; returns 0.50&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@sampleCount&lt;/code&gt;: A count of the number of log events from a selected time period and specified log groups that match an identified pattern.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@severityLabel&lt;/code&gt;: The log severity or level, which indicates the type of information contained in a log. For example, Error, Warning, Info, or Debug.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;In conclusion: &lt;code&gt;pattern&lt;/code&gt; command is something I'm definitely adding to my workflow and my only wish is that it was available sooner. It's a huge time saver and it can help you get to the root cause of the issue much faster.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudwatch</category>
    </item>
    <item>
      <title>Match case-insensitive patterns when using CloudWatch Logs Insights</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Tue, 10 Oct 2023 12:10:58 +0000</pubDate>
      <link>https://dev.to/aws-heroes/match-case-insensitive-patterns-when-using-cloudwatch-logs-insights-1k2e</link>
      <guid>https://dev.to/aws-heroes/match-case-insensitive-patterns-when-using-cloudwatch-logs-insights-1k2e</guid>
      <description>&lt;p&gt;👋&lt;/p&gt;

&lt;p&gt;I found myself Googling (or rather - ChatGPTing) this one too many times so I decided to write it down.&lt;/p&gt;




&lt;p&gt;If you're looking for errors in your CloudWatch Logs you can use CloudWatch Logs Insights to query your logs. One of the most commonly used commands is &lt;code&gt;filter&lt;/code&gt; which allows you to filter your logs that match one or more conditions, here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields @timestamp, @message
| filter (range&amp;gt;3000 and accountId=123456789012)
| sort @timestamp desc
| limit 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be honest I rarely find myself using filter like this, but I often use it to filter logs that match a specific pattern, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fields @timestamp, @message, @logStream, @log
| filter @message like /error/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;like&lt;/code&gt; keyword here - this is a signal for CloudWatch Logs Insights to treat the pattern as a regular expression. (You can use &lt;code&gt;=~&lt;/code&gt; instead of &lt;code&gt;like&lt;/code&gt; if you want, e.g. &lt;code&gt;filter @message =~ /error/&lt;/code&gt; but I personally find it more confusing to read).&lt;/p&gt;

&lt;p&gt;There is one problem with this query, suppose that our error log entry looks 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;console.log({
  message: "Error: cannot create user",
  timestamp: new Date().toUTCString(),
  requestId: faker.random.uuid(),
  userId: faker.random.uuid(),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Obviously don't use &lt;code&gt;faker.random.uuid()&lt;/code&gt; in prod, this is just an example).&lt;/p&gt;

&lt;p&gt;If we type &lt;code&gt;filter @message like /error/&lt;/code&gt; we won't get any results because the pattern is case-sensitive. To make it case-insensitive we need to add &lt;code&gt;(?i)&lt;/code&gt; to the beginning of the pattern, 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;fields @timestamp, @message, @logStream, @log
| filter @message like /(?i)error/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will match &lt;code&gt;error&lt;/code&gt;, &lt;code&gt;Error&lt;/code&gt;, &lt;code&gt;ERROR&lt;/code&gt; or even &lt;code&gt;eRroR&lt;/code&gt; and we'll get the results we're looking for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Additional tip:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One more thing - if you want to filter all logs that are &lt;strong&gt;not&lt;/strong&gt; errors (e.g. if you don't want to ruin your weekend), you can use &lt;code&gt;not like&lt;/code&gt; syntax, 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;fields @timestamp, @message, @logStream, @log
| filter @message not like /(?i)error/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aws</category>
      <category>cloudwatch</category>
    </item>
    <item>
      <title>Intro to CloudWatch Logs Live Tail</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Mon, 04 Sep 2023 15:46:21 +0000</pubDate>
      <link>https://dev.to/aws-heroes/intro-to-cloudwatch-logs-live-tail-43mg</link>
      <guid>https://dev.to/aws-heroes/intro-to-cloudwatch-logs-live-tail-43mg</guid>
      <description>&lt;p&gt;AWS has &lt;a href="https://aws.amazon.com/about-aws/whats-new/2023/06/live-tail-amazon-cloudwatch-logs/"&gt;recently introduced&lt;/a&gt; a new feature for real-time log analytics: CloudWatch Logs Live Tail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can now view your logs interactively in real-time as they’re ingested, which helps you to analyze and resolve issues across your systems and applications.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To access this feature, log in to your AWS account, choose &lt;strong&gt;Logs-&amp;gt;Live tail&lt;/strong&gt;, select log groups of interest (up to 10), apply filters as needed and you're good to go.&lt;/p&gt;

&lt;p&gt;Sample filters &lt;a href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CloudWatchLogs_LiveTail.html"&gt;source&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;error 404&lt;/code&gt; displays only log events that include both error and 404&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;?Error ?error&lt;/code&gt; displays log events that include either Error or error&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-INFO&lt;/code&gt; displays all log events that don't include INFO&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;{ $.eventType = "UpdateTrail" }&lt;/code&gt; displays all JSON log events where the value of the event type field is UpdateTrail&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XOdbuzAC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ycu76i7ft8deem24bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XOdbuzAC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e6ycu76i7ft8deem24bf.png" alt="Screenshot of CloudWatch Logs Live Tail UI" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature overview, as described by AWS:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Real-Time Viewing: See logs interactively as they're ingested. No more waiting.&lt;/li&gt;
&lt;li&gt;Rich User Experience: Easily view and detect issues in incoming logs.&lt;/li&gt;
&lt;li&gt;Granular Controls: Filter, highlight, pause, and replay logs on-the-go.&lt;/li&gt;
&lt;li&gt;Quick Validation: Ideal for DevOps teams, validate processes, configuration changes, and deployment success in real time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pqiYmb7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ky3mftfvtt9isql5fme2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pqiYmb7f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ky3mftfvtt9isql5fme2.png" alt="Screenshot of CloudWatch Logs Live Tail UI" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you get tired of watching your logs fly in real time, you can either copy or download the logs for further analysis as CSV, JSON or XLSX (for hard core Excel fans out there).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Paysda0G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hv3tunfv276pumhcse0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Paysda0G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hv3tunfv276pumhcse0o.png" alt="Screenshot of CloudWatch Logs Live Tail UI" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All logs can be filtered based on log group, log stream and custom filter patterns. For instance you can find all &lt;code&gt;ERROR&lt;/code&gt; logs in a given log group.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Overall I think this is a great addition to the CloudWatch Logs ecosystem. It's a simple feature that can save you a lot of time when debugging issues in your application. Not that I ever have a production outage 😎, but if I did, I'd definitely use this feature to help me resolve it. The only weird bit is the &lt;strong&gt;N events/sec&lt;/strong&gt; screen, in my testing it was not entirely accurate, but then again - my sample &lt;code&gt;UserService&lt;/code&gt; is not exactly a production-grade application.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloudwatch</category>
    </item>
    <item>
      <title>AWS Lambda storage options</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Wed, 21 Sep 2022 19:46:18 +0000</pubDate>
      <link>https://dev.to/aws-heroes/aws-lambda-storage-options-o5p</link>
      <guid>https://dev.to/aws-heroes/aws-lambda-storage-options-o5p</guid>
      <description>&lt;p&gt;If you're building a serverless app, you're most likely using AWS Lambda.&lt;/p&gt;

&lt;p&gt;Lambda functions are (by design) emphemeral, which means that their execution environments exist briefly when the function is invoked. Which presents an interesting challenge:&lt;/p&gt;

&lt;h2&gt;
  
  
  What if I need access to storage in my Lambda function?
&lt;/h2&gt;

&lt;p&gt;The seemingly obvious answer to this question is "use a database".&lt;/p&gt;

&lt;p&gt;As with most obvious answers, this one is not entirely correct. For instance, storing third-party libraries in DynamoDB would surely be an interesting idea, but not exactly practical.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Good luck storing node_modules in DynamoDB, by the way.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Other potential use cases include machine learning models, image processing, the output of your business-specific compute operation and more.&lt;/p&gt;

&lt;p&gt;The goal of this post is to give you an overview of the different storage options available to you when building serverless applications with AWS Lambda, their differences and common use-cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon S3
&lt;/h2&gt;

&lt;p&gt;Amazon S3 is a widely popular object storage service, offering high availability and &lt;a href="https://aws.amazon.com/s3/faqs/"&gt;11 9's of durability&lt;/a&gt;. It's a great choice for storing unstructured static assets, such as images, videos, documents, etc.&lt;/p&gt;

&lt;p&gt;S3 is a common element of serverless architecture diagrams, &lt;a href="https://aws.amazon.com/blogs/compute/choosing-between-aws-lambda-data-storage-options-in-web-apps/"&gt;to quote AWS docs&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;S3 has important event integrations for serverless developers. It has a native integration with Lambda, which allows you to invoke a function in response to an S3 event. This can provide a scalable way to trigger application workflows when objects are created or deleted in S3.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not only can you invoke a Lambda function whenever an object is placed into an S3 bucket, but you can also both retrieve and send data to/from S3 in your Lambda function invocation. This is often useful because Lambda can be &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html"&gt;invoked with 6MB payload in a synchronous manner and 256kB in an asynchronous manner&lt;/a&gt;. Should you need a larger dataset, you can consider fetching that from S3.&lt;/p&gt;

&lt;p&gt;Storing data in S3 has an additional benefit, given how well it integrates with other AWS services. For instance, you can use &lt;a href="https://aws.amazon.com/athena/"&gt;Amazon Athena&lt;/a&gt; to query your S3 data, or &lt;a href="https://aws.amazon.com/rekognition/"&gt;Amazon Rekognition&lt;/a&gt; to analyze it. Additionally you can use &lt;a href="https://aws.amazon.com/glue/"&gt;AWS Glue&lt;/a&gt; to perform extract, transform, and loan (ETL) operations. To create ad hoc visualizations and business analysis reports, &lt;a href="https://aws.amazon.com/quicksight/"&gt;Amazon QuickSight&lt;/a&gt; can connect to your S3 buckets and produce interactive dashboards.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://aws.amazon.com/s3/faqs/"&gt;S3 FAQ to learn more&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporary storage, also known as /tmp
&lt;/h2&gt;

&lt;p&gt;Another interesting storage option available for AWS Lambda functions is its execution environment file system, available at &lt;code&gt;/tmp&lt;/code&gt;. There are multiple factors to consider before using &lt;code&gt;/tmp&lt;/code&gt; as a storage option:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It has a fixed size of 512MB&lt;/li&gt;
&lt;li&gt;Because of the way Lambda is designed, the same execution environment will be reused by multiple invocations to &lt;a href="https://cloudash.dev/blog/best-practices-for-optimizing-lambda-functions"&gt;optimize performance&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Each new execution environment starts with an empty &lt;code&gt;/tmp&lt;/code&gt; directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short - &lt;code&gt;/tmp&lt;/code&gt; works well for ephemeral storage which should be shared between invocations with an added benefit of fast I/O throughput. As an example you may want to fetch a machine learning model, store it in &lt;code&gt;/tmp&lt;/code&gt; and use it in your Lambda function. That way you won't need to fetch it from S3 during every invocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amazon EFS for Lambda
&lt;/h2&gt;

&lt;p&gt;Speaking of file systems - AWS Lambda comes with a support for EFS. Amazon EFS is a fully managed, elastic, shared file system that integrates with other AWS services.&lt;/p&gt;

&lt;p&gt;The biggest difference between aforementioned &lt;code&gt;/tmp&lt;/code&gt; is that EFS is a &lt;strong&gt;durable&lt;/strong&gt; storage that offers high availability.&lt;/p&gt;

&lt;p&gt;You may wonder whether mounting a file system increases the cold start time, according to AWS:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Lambda service mounts EFS file systems when the execution environment is prepared. This happens in parallel with other initialization operations so typically does not impact cold start latency. If the execution environment is warm from previous invocations, the mount is already prepared. To use EFS, your Lambda function must be in the same VPC as the file system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Potential use cases for EFS include ingesting/writing large files durably, for instance large zip archives (e.g. machine learning models). Since EFS is a file system, you can append to existing files (unlike S3 where a new version of a whole object gets created).&lt;/p&gt;

&lt;h2&gt;
  
  
  Lambda layers
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Insert Shrek onion quote here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Lambda functions can (and often do) use additional libraries as a part of the deployment package (after all, who can live without &lt;code&gt;node_modules&lt;/code&gt;?). Each function can have up to 5 layers, which are counted in the maximum deployment size of 50MB (zipped).&lt;/p&gt;

&lt;p&gt;Since layers are not temporary, they are not available in &lt;code&gt;/tmp&lt;/code&gt; - instead, they're stored in &lt;code&gt;/opt&lt;/code&gt; directory. There's an added benefit of using layers - they can be shared with other AWS accounts (&lt;a href="https://cloudash.dev/blog/aws-multi-account-benefits"&gt;you may want to read about benefits of using multiple AWS accounts&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Using Lambda layers does not incur any additional costs.&lt;/p&gt;

&lt;p&gt;Read more about layers in &lt;a href="https://aws.amazon.com/blogs/compute/using-lambda-layers-to-simplify-your-development-process/"&gt;using Lambda layers to simplify your development process&lt;/a&gt; on &lt;a href="https://aws.amazon.com/blogs/compute/"&gt;AWS Compute Blog&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing the different data storage options
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Amazon S3&lt;/th&gt;
&lt;th&gt;/tmp&lt;/th&gt;
&lt;th&gt;Lambda Layers&lt;/th&gt;
&lt;th&gt;Amazon EFS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Maximum size&lt;/td&gt;
&lt;td&gt;Elastic&lt;/td&gt;
&lt;td&gt;512 MB&lt;/td&gt;
&lt;td&gt;50 MB (direct upload; larger if from S3).&lt;/td&gt;
&lt;td&gt;Elastic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Persistence&lt;/td&gt;
&lt;td&gt;Durable&lt;/td&gt;
&lt;td&gt;Ephemeral&lt;/td&gt;
&lt;td&gt;Durable&lt;/td&gt;
&lt;td&gt;Durable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;td&gt;Static&lt;/td&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage type&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;File system&lt;/td&gt;
&lt;td&gt;Archive&lt;/td&gt;
&lt;td&gt;File system&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lambda event source integration&lt;/td&gt;
&lt;td&gt;Native&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operations supported&lt;/td&gt;
&lt;td&gt;Atomic with versioning&lt;/td&gt;
&lt;td&gt;Any file system operation&lt;/td&gt;
&lt;td&gt;Immutable&lt;/td&gt;
&lt;td&gt;Any file system operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object tagging&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Object metadata&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pricing model&lt;/td&gt;
&lt;td&gt;Storage + requests + data transfer&lt;/td&gt;
&lt;td&gt;Included in Lambda&lt;/td&gt;
&lt;td&gt;Included in Lambda&lt;/td&gt;
&lt;td&gt;Storage + data transfer + throughput&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharing/permissions model&lt;/td&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;Function-only&lt;/td&gt;
&lt;td&gt;IAM&lt;/td&gt;
&lt;td&gt;IAM + NFS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source for AWS Glue&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Source for Amazon QuickSight&lt;/td&gt;
&lt;td&gt;Y&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;td&gt;N&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relative data access speed from Lambda&lt;/td&gt;
&lt;td&gt;Fast&lt;/td&gt;
&lt;td&gt;Fastest&lt;/td&gt;
&lt;td&gt;Fastest&lt;/td&gt;
&lt;td&gt;Very fast&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Source: &lt;a href="https://aws.amazon.com/blogs/compute/choosing-between-aws-lambda-data-storage-options-in-web-apps/"&gt;https://aws.amazon.com/blogs/compute/choosing-between-aws-lambda-data-storage-options-in-web-apps/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Guide to AWS Lambda Function URLs</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Tue, 23 Aug 2022 19:43:28 +0000</pubDate>
      <link>https://dev.to/aws-heroes/guide-to-aws-lambda-function-urls-4eee</link>
      <guid>https://dev.to/aws-heroes/guide-to-aws-lambda-function-urls-4eee</guid>
      <description>&lt;p&gt;For the longest time, the go-to way of calling an AWS Lambda function via HTTP(S) was to put an API Gateway in front of it. While this works well (and it's still a required pattern for many, many serverless use cases), sometimes developers wanted to &lt;em&gt;"just call an AWS Lambda function"&lt;/em&gt; by sending a network request.&lt;/p&gt;

&lt;p&gt;Introducing &lt;a href="https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/"&gt;AWS Lambda Function URLs&lt;/a&gt; - a new feature in AWS Lambda that allows you to call a Lambda function without an API Gateway.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Lambda Function URL?
&lt;/h2&gt;

&lt;p&gt;Simply put - it's an URL that you can send a network request to to call a Lambda function. An example URL may look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://vg7sczk62ycloct63yi3wjpoj40sgkuz.lambda-url.eu-central-1.on.aws/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, in general:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://&amp;lt;url-id&amp;gt;.lambda-url.&amp;lt;region&amp;gt;.on.aws/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lambda function URL can point to either &lt;code&gt;$LATEST&lt;/code&gt; or to an &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-aliases.html"&gt;user-defined alias&lt;/a&gt;. Even though no additional resources are required (e.g. API Gateway or an ALB), function URL is a separate CloudFormation resource which needs to be provisioned separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do I create an AWS Lambda function URL?
&lt;/h2&gt;

&lt;p&gt;You can create an AWS Lambda function URL via:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Management Console (Cloudash team does &lt;strong&gt;not&lt;/strong&gt; recommend so-called ClickOps for production usage, use IaC instead)&lt;/li&gt;
&lt;li&gt;AWS CLI&lt;/li&gt;
&lt;li&gt;AWS CloudFormation&lt;/li&gt;
&lt;li&gt;AWS Serverless Application Model (AWS SAM)&lt;/li&gt;
&lt;li&gt;AWS CDK&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Could you give me an example?
&lt;/h2&gt;

&lt;p&gt;Sure thing, this is how one might create an AWS Lambda function + and a function url to call it directly using AWS CDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;LambdaUrlStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;myLambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myLambda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.handler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODEJS_16_X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambdaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CfnUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambdaUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;targetFunctionArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myLambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionArn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;authType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionUrlAuthType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And yes, &lt;code&gt;authType: cdk.aws_lambda.FunctionUrlAuthType.NONE&lt;/code&gt; is not exactly secure. Keep reading to learn more:&lt;/p&gt;

&lt;h2&gt;
  
  
  Security and auth model for Lambda function URLs
&lt;/h2&gt;

&lt;p&gt;Controlling access to Lambda function URLs is performed using the &lt;code&gt;AuthType&lt;/code&gt; parameter combined with &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html"&gt;resource-based policies&lt;/a&gt; attached to a particular function.&lt;/p&gt;

&lt;p&gt;To quote AWS docs, there are two possible values of &lt;code&gt;AuthType&lt;/code&gt; parameter:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;AWS_IAM&lt;/code&gt; – Lambda uses AWS Identity and Access Management (IAM) to authenticate and authorize requests based on the IAM principal's identity policy and the function's resource-based policy. Choose this option if you want only authenticated IAM users and roles to invoke your function via the function URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;NONE&lt;/code&gt; – Lambda doesn't perform any authentication before invoking your function. However, your function's resource-based policy is always in effect and must grant public access before your function URL can receive requests. Choose this option to allow public, unauthenticated access to your function URL.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;AWS_IAM&lt;/code&gt; auth type
&lt;/h3&gt;

&lt;p&gt;When a Lambda function URL has an &lt;code&gt;AWS_IAM&lt;/code&gt; &lt;code&gt;AuthType&lt;/code&gt; then whoever needs to invoke this particular Lambda function URL must have the &lt;code&gt;lambda:InvokeFunctionUrl&lt;/code&gt; permission for a particular Lambda function.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;lambda:InvokeFunctionUrl&lt;/code&gt; is &lt;strong&gt;different&lt;/strong&gt; than &lt;code&gt;lambda:InvokeFunction&lt;/code&gt;, so you may need to adjust your IAM permissions accordingly when opting in to use this feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;NONE&lt;/code&gt; auth type
&lt;/h3&gt;

&lt;p&gt;When a Lambda function URL &lt;code&gt;AuthType&lt;/code&gt; is set to &lt;code&gt;NONE&lt;/code&gt; then &lt;strong&gt;any&lt;/strong&gt; unauthenticated user with your function URL can invoke your function - proceed with caution. This might be useful whenever you might want to allow public access to your function URL e.g. via a web browser.&lt;/p&gt;

&lt;p&gt;Even though the auth type is set to &lt;code&gt;NONE&lt;/code&gt; and Lambda does not use IAM to authenticate requests to a function URL, whoever tries to the function needs to have the &lt;code&gt;lambda:InvokeFunctionUrl&lt;/code&gt; permissions.&lt;/p&gt;

&lt;p&gt;An example function URL invoke policy for all unauthenticated principals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "lambda:InvokeFunctionUrl",
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "NONE"
                }
            }
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When creating a function URL with auth type set to &lt;code&gt;NONE&lt;/code&gt; via the AWS Console or AWS SAM, the resource-based policy statement listed above will be automatically created for you. When e.g. using AWS SDK you'd need to create it yourself, example of how one might want to do this below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;aws-cdk-lib&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;constructs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;LambdaUrlStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Construct&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;props&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;myLambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myLambda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Code&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;index.handler&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODEJS_16_X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambdaUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CfnUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambdaUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;targetFunctionArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myLambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionArn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;authType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FunctionUrlAuthType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NONE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambdaPermission&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CfnResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambdaPermission&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AWS::Lambda::Permission&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lambda:InvokeFunctionUrl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;FunctionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myLambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionArn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;Principal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;FunctionUrlAuthType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NONE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pricing
&lt;/h2&gt;

&lt;p&gt;Lambda function URLs are included in AWS Lambda's pricing - there are no additional charges for using this feature (and you can save money on &lt;strong&gt;not&lt;/strong&gt; using API Gateway)&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits
&lt;/h2&gt;

&lt;p&gt;Lambda function URLs share the same limits as AWS Lambda functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;6 MB response and request payload size&lt;/li&gt;
&lt;li&gt;Default 1,000 up to tens of thousands TPS&lt;/li&gt;
&lt;li&gt;15-minute timeout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short - there is no additional cost, no additional timeout and payload limits when choosing to use Lambda function URLs.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html"&gt;official AWS docs to learn more&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, what's the difference between Function URLs and API Gateway? Are Function URLs objectively better?
&lt;/h2&gt;

&lt;p&gt;Not exactly, there's always a tradeoff.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;API Gateway REST APIs&lt;/th&gt;
&lt;th&gt;Function URLs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Payload limit&lt;/td&gt;
&lt;td&gt;6 MB (with AWS Lambda)&lt;/td&gt;
&lt;td&gt;6 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Max timeout&lt;/td&gt;
&lt;td&gt;29 seconds&lt;/td&gt;
&lt;td&gt;Up to 15 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SDK generation&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;from $3.50/million for first 333 million&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS WAF&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Usage plans&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request/response validation and transformation&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=B-Mz-HTSavM"&gt;Source - AWS Summit SF 2022 - Best practices for building interactive applications with AWS Lambda (CON302)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Function URLs have a greatly extended timeout (up to 15 minutes) compared to API Gateway + Lambda, with the tradeoff of highly reduced security/usage limits capabilities.&lt;/p&gt;

&lt;p&gt;To quote &lt;a href="https://aws.amazon.com/blogs/aws/announcing-aws-lambda-function-urls-built-in-https-endpoints-for-single-function-microservices/"&gt;Announcing AWS Lambda Function URLs&lt;/a&gt; blogpost:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Function URLs are best for use cases where you must implement a single-function microservice with a public endpoint that doesn’t require the advanced functionality of API Gateway, such as request validation, throttling, custom authorizers, custom domain names, usage plans, or caching. [...] It is also the simplest way to invoke your Lambda functions during research and development without leaving the Lambda console or integrating additional services.&lt;/p&gt;

&lt;p&gt;Use API Gateway to take advantage of capabilities like JWT/custom authorizers, request/response validation and transformation, usage plans, built-in AWS WAF support, and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Learn more in &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html"&gt;Lambda function URLs documentation&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Guide to default AWS Lambda environment variables</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Mon, 06 Jun 2022 19:34:43 +0000</pubDate>
      <link>https://dev.to/aws-heroes/guide-to-default-aws-lambda-environment-variables-10kh</link>
      <guid>https://dev.to/aws-heroes/guide-to-default-aws-lambda-environment-variables-10kh</guid>
      <description>&lt;p&gt;AWS Lambda runtimes set a number of default environment variables during initialization of every serverless function.&lt;/p&gt;

&lt;p&gt;The following variables are &lt;strong&gt;reserved&lt;/strong&gt; and cannot be set in your function configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;_HANDLER&lt;/code&gt; - The location of a functions's handler.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;_X_AMZN_TRACE_ID&lt;/code&gt; - &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html" rel="noopener noreferrer"&gt;X-Ray tracing header&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_REGION&lt;/code&gt; - The region the function is running in (we all know it's &lt;code&gt;us-east-1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_EXECUTION_ENV&lt;/code&gt; - The &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html" rel="noopener noreferrer"&gt;AWS Lambda runtime identifier&lt;/a&gt;. Examples: &lt;code&gt;AWS_Lambda_nodejs14.x&lt;/code&gt;, &lt;code&gt;AWS_Lambda_java8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_FUNCTION_NAME&lt;/code&gt; - The name of the function (which is either "hello world" or IaC randomly generated one, there's no between).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_FUNCTION_MEMORY_SIZE&lt;/code&gt; - The amount of memory allocated to the function (e.g. 1024MB).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_FUNCTION_VERSION&lt;/code&gt; - The version of the function (e.g. &lt;code&gt;$LATEST&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_INITIALIZATION_TYPE&lt;/code&gt; - The initialization type of the function, can be either &lt;code&gt;on-demand&lt;/code&gt; or &lt;code&gt;provisioned-concurrency&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_LOG_GROUP_NAME&lt;/code&gt; - The name of the CloudWatch log group.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_LOG_STREAM_NAME&lt;/code&gt; - The name of the CloudWatch stream.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_ACCESS_KEY&lt;/code&gt;, &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt;, &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt;, &lt;code&gt;AWS_SESSION_TOKEN&lt;/code&gt; - The access keys obtained from the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html" rel="noopener noreferrer"&gt;function's execution role&lt;/a&gt;. Be careful with those, read &lt;a href="https://github.com/puresec/sas-top-10#sas-7-insecure-application-secrets-storage" rel="noopener noreferrer"&gt;SAS-7: Insecure Application Secrets Storage&lt;/a&gt; for guidance. This post on &lt;a href="https://www.trendmicro.com/fr_fr/devops/21/g/security-for-aws-lambda-serverless-applications.html" rel="noopener noreferrer"&gt;Security for AWS Lambda Serverless Applications&lt;/a&gt; is also a good place to start.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_RUNTIME_API&lt;/code&gt; - The host and port of the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html" rel="noopener noreferrer"&gt;AWS Lambda runtime API&lt;/a&gt;, example: &lt;code&gt;127.0.0.1:9001&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAMBDA_TASK_ROOT&lt;/code&gt; - The path to your Lambda function code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LAMBDA_RUNTIME_DIR&lt;/code&gt; - The path to runtime libraries&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TZ&lt;/code&gt; - The timezone information, e.g. &lt;code&gt;:UTC'&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In addition to that, AWS Lambda runtime sets additional variables that are &lt;strong&gt;not&lt;/strong&gt; reserved and can be extended in your function configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;LANG&lt;/code&gt; - The language of your function's runtime, e.g. &lt;code&gt;en_US.UTF-8&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PATH&lt;/code&gt; - The execution path, e.g. &lt;code&gt;/var/lang/bin:/usr/local/bin:/usr/bin/:/bin:/opt/bin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LD_LIBRARY_PATH&lt;/code&gt; - The system library path, e.g. &lt;code&gt;/var/lang/lib:/lib64: /usr/lib64:/var/runtime: /var/runtime/lib:/var/task:/var/task/lib:/opt/lib&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_XRAY_CONTEXT_MISSING&lt;/code&gt; - Quoting &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;: "For X-Ray tracing, Lambda sets this to &lt;code&gt;LOG_ERROR&lt;/code&gt; to avoid throwing runtime errors from the X-Ray SDK."&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_XRAY_DAEMON_ADDRESS&lt;/code&gt; - The IP address and port of the X-Ray daemon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also a few runtime-specific environment variables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NODE_PATH&lt;/code&gt; - A &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-nodejs.html" rel="noopener noreferrer"&gt;node.js&lt;/a&gt; env variable, containing node.js library path, e.g. &lt;code&gt;/opt/nodejs/node14/node_modules: /opt/nodejs/node_modules: /var/runtime/node_modules:/var/runtime:/var/task&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PYTHONPATH&lt;/code&gt; - The Python library path&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GEM_PATH&lt;/code&gt; - The Ruby library path&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_LAMBDA_DOTNET_PREJIT&lt;/code&gt; - Quoting &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime" rel="noopener noreferrer"&gt;the docs&lt;/a&gt;: "For the .NET 3.1 runtime, set this variable to enable or disable .NET 3.1 specific runtime optimizations. Values include &lt;code&gt;always&lt;/code&gt;, &lt;code&gt;never&lt;/code&gt;, and &lt;code&gt;provisioned-concurrency&lt;/code&gt;."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Stay on top of your logs. ⚡️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloudash.dev%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fmedia%252Fcloudash_function.6e0454ea.png%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcloudash.dev%2F_next%2Fimage%3Furl%3D%252F_next%252Fstatic%252Fmedia%252Fcloudash_function.6e0454ea.png%26w%3D3840%26q%3D75" alt="Cloudash screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Introducing &lt;a href="https://cloudash.dev" rel="noopener noreferrer"&gt;Cloudash&lt;/a&gt;, a desktop app for monitoring your serverless services performance, invocations, errors and more.&lt;/p&gt;

&lt;p&gt;Did a production incident happen last week? Or 20 seconds ago? With Cloudash you can search, filter and browse your serverless logs and metrics effortlessly.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Benefits of multi-account strategy on AWS</title>
      <dc:creator>Tomasz Łakomy</dc:creator>
      <pubDate>Mon, 23 May 2022 19:30:42 +0000</pubDate>
      <link>https://dev.to/aws-heroes/benefits-of-multi-account-strategy-on-aws-5g33</link>
      <guid>https://dev.to/aws-heroes/benefits-of-multi-account-strategy-on-aws-5g33</guid>
      <description>&lt;p&gt;One of major benefits of adopting AWS Cloud in your organization is the ease of creating and destroying resources in your account. Entire production environments consisting of multiple resources can be deployed (e.g. using &lt;a href="https://cloudash.dev/blog/what-is-aws-cdk"&gt;AWS CDK&lt;/a&gt;), tested and destroyed should a need arise.&lt;/p&gt;

&lt;p&gt;As the company grows, so do the number of resources it requires. This can be a challenge for the team as it needs to be able to manage and deploy all the resources in a single account. AWS customers want the ability to build, move fast, iterate while maintaining the best security practices.&lt;/p&gt;

&lt;p&gt;When multiple teams work with a single AWS account, ownership boundaries become blurred, cost optimization and visibility become a challenge, and the blast radius for potential security incidents becomes ever larger.&lt;/p&gt;

&lt;p&gt;As such, a recommended approach by AWS is to set up &lt;a href="https://aws.amazon.com/organizations/getting-started/best-practices/"&gt;a multi-account AWS environment&lt;/a&gt;. There are number of benefits to this approach, including (but not limited to):&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost optimization
&lt;/h2&gt;

&lt;p&gt;An AWS account is the default cost allocation unit. As such, having multiple teams working with a single account can make cost optimization challenging (unless you're exceptionally good at managing tags for all resources provisioned in that account).&lt;/p&gt;

&lt;p&gt;Having a bill shared by all teams rise by 20% month-by-month can trigger a long investigation into the root cause of the cost issue, which can be a costly process (bear in mind that developer's time is &lt;strong&gt;expensive&lt;/strong&gt;, quite often more costly than the cost of an AWS environment they operate in)&lt;/p&gt;

&lt;p&gt;Using multiple accounts (e.g. one account per team) massively improves the visibility of costs caused by each team's activity (if TeamX AWS bill rises by 20% it &lt;em&gt;maaaay&lt;/em&gt; be that super large EC2 instance they forgot to shut down).&lt;/p&gt;

&lt;p&gt;On the other hand - having greater visibility into the costs of each team can help avoid TeamA spending time on &lt;a href="https://cloudash.dev/blog/best-practices-for-optimizing-lambda-functions"&gt;improving the performance of a single Lambda function by 20%&lt;/a&gt; (and saving $5.50 per month) when the real problem is a huge TeamB's NAT Gateway bill. In addition to that - having better visibility into their costs can help technical teams make better decisions about their architecture and deployment strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Grouping workloads based business needs and ownership
&lt;/h2&gt;

&lt;p&gt;Developers usually need a development environment to test their code in, a staging environment (to pretend that it's production) and a production environment (to actually deploy the code to the delight of their customers).&lt;/p&gt;

&lt;p&gt;While setting up those environments in a single AWS account is possible (although challenging), a better solution is to split those workloads by environment &lt;strong&gt;and&lt;/strong&gt; by team.&lt;/p&gt;

&lt;p&gt;Given two teams (TeamX and TeamY) that maintain two separate products (ProductX and ProductY), you may want to consider a following AWS account split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ProductXDevAccount (owned by TeamX)&lt;/li&gt;
&lt;li&gt;ProductXStagingAccount (owned by TeamX)&lt;/li&gt;
&lt;li&gt;ProductXProdAccount (owned by TeamX)&lt;/li&gt;
&lt;li&gt;ProductYDevAccount (owned by TeamY)&lt;/li&gt;
&lt;li&gt;ProductYStagingAccount (owned by TeamY)&lt;/li&gt;
&lt;li&gt;ProductYProdAccount (owned by TeamY)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Following this approach allows you to specify necessary guardrails (governance rules for security, operations, and compliance) to each of those accounts.&lt;/p&gt;

&lt;p&gt;As an example, while developers should be able to do more or less whatever they want (within limits, obviously) in a development account, they shouldn't be able to casually delete a DynamoDB table in a production account (nor should they have read/write access to its data, depending on data compliance requirements).&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying security controls per environment
&lt;/h2&gt;

&lt;p&gt;To continue the above example, you may want to apply security controls to each of those accounts. Maintaining different security policies for development/staging/prod environments in a single account is challenging and error-prone (a small mixup of IAM policies can have drastic consequences for your business). Having separate accounts with clearly defined roles (since e.g. development account should &lt;strong&gt;never&lt;/strong&gt; be used for serving production traffic) helps with establishing proper security controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minimising blast radius
&lt;/h2&gt;

&lt;p&gt;Speaking of security, what happens when you &lt;strong&gt;do&lt;/strong&gt; have a security incident? As &lt;a href="https://twitter.com/Werner"&gt;Dr. Werner Vogels&lt;/a&gt; says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everything breaks, all the time&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Security incidents are &lt;strong&gt;never&lt;/strong&gt; fun, but if they do happen - it's better to have one environment of one service affected than your entire tech stack (if you were to run everything in a single account). AWS accounts are security boundaries provided by AWS, for instance if a development account is compromised, the production database is safe (as it's stored in a completely different account and as such - much, much harder to access by the attacker).&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits allocation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/servicequotas/latest/userguide/intro.html"&gt;AWS Service Quotas&lt;/a&gt; (a.k.a. limits) are set up on per account basis. Separating workloads into different accounts gives each account a well-defined, individual quota.&lt;/p&gt;

&lt;p&gt;As an example, by default you can create up to &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/BucketRestrictions.html"&gt;100 S3 buckets in an AWS account&lt;/a&gt;. With multiple teams working with a single account, this limit can quickly be exceeded and no new buckets can be created (side note: it's possible to raise an account bucket limit to a maximum of 1,000 buckets). Using multiple AWS accounts in your organization can help you mitigate those limitations.&lt;/p&gt;

&lt;p&gt;In addition to that, because Service Quotas and request rate limits are allocated for each account, having a multi-account strategy can allow you to e.g. &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/lambda-concurrency-limit-increase/#:~:text=The%20default%20concurrency%20limit%20per,concurrency%20limit%20for%20Lambda%20functions."&gt;raise AWS Lambda Concurrent Executions limit&lt;/a&gt; only in production account (e.g. before Black Friday) while keeping it at the default in development and staging accounts to avoid unnecessary costs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promoting innovation and agility
&lt;/h2&gt;

&lt;p&gt;Apart from staging/production environments, you may want to consider deploying creating other types of accounts for developers to use. To quote &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/benefits-of-using-multiple-aws-accounts.html#distribute-aws-service-quotas-and-api-request-rate-limits"&gt;AWS documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sandbox accounts&lt;/strong&gt; are typically disconnected from your enterprise services and do not provide access to your internal data, but offer the greatest freedom for experimentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Development accounts&lt;/strong&gt; typically provide limited access to your enterprise services and development data, but can more readily support day-to-day experimentation with your enterprise approved AWS services, formal development, and early testing work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your tech organization is going through a cloud transformation, it's &lt;strong&gt;definitely&lt;/strong&gt; better for engineers to experiment with new services and technologies in their own sandbox accounts (as opposed to your production environment). This way, you can test out new features and see how they work before deploying them to production.&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;If you'd like to learn more about best pracitices for AWS Multi-Account strategy, consult the &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/organizing-your-aws-environment.html"&gt;Organizing Your AWS Environment Using Multiple Accounts&lt;/a&gt; whitepaper.&lt;/p&gt;




&lt;h2&gt;
  
  
  Stay on top of your logs. ⚡️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RXm-FJPk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cloudash.dev/_next/image%3Furl%3D%252F_next%252Fstatic%252Fmedia%252Fcloudash_function.6e0454ea.png%26w%3D3840%26q%3D75" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RXm-FJPk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cloudash.dev/_next/image%3Furl%3D%252F_next%252Fstatic%252Fmedia%252Fcloudash_function.6e0454ea.png%26w%3D3840%26q%3D75" alt="Cloudash screenshot" width="880" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Introducing &lt;a href="https://cloudash.dev"&gt;Cloudash&lt;/a&gt;, a desktop app for monitoring your serverless services performance, invocations, errors and more.&lt;/p&gt;

&lt;p&gt;Did a production incident happen last week? Or 20 seconds ago? With Cloudash you can search, filter and browse your serverless logs and metrics effortlessly.&lt;/p&gt;

&lt;p&gt;Search for whatever you want, whenever you want. Cloudash comes with built-in filtering capabilities enabling to get to the bottom of your problems faster than ever before.&lt;/p&gt;

&lt;p&gt;Get started &lt;a href="https://cloudash.dev"&gt;here&lt;/a&gt;.&lt;/p&gt;

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