<?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: Sebastian Hesse</title>
    <description>The latest articles on DEV Community by Sebastian Hesse (@seeebiii).</description>
    <link>https://dev.to/seeebiii</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%2F573325%2Fe6e7ca63-d6d2-42c3-920f-359e9a26bc42.jpeg</url>
      <title>DEV Community: Sebastian Hesse</title>
      <link>https://dev.to/seeebiii</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/seeebiii"/>
    <language>en</language>
    <item>
      <title>Migrating a CDK Construct to projen and jsii</title>
      <dc:creator>Sebastian Hesse</dc:creator>
      <pubDate>Mon, 01 Mar 2021 09:00:00 +0000</pubDate>
      <link>https://dev.to/seeebiii/migrating-a-cdk-construct-to-projen-and-jsii-4g5</link>
      <guid>https://dev.to/seeebiii/migrating-a-cdk-construct-to-projen-and-jsii-4g5</guid>
      <description>&lt;p&gt;CDK constructs are a great way to combine best practices and simplify your infrastructure code. Have you ever written your own CDK construct? Writing a construct is easy using the CDK CLI. But soon you’ll discover the hard parts: Keeping all dependencies updated; Aligning the CDK dependency versions to not have version conflicts; And publishing your CDK construct to multiple repositories. &lt;code&gt;projen&lt;/code&gt; makes the CDK construct setup and maintenance a lot easier. And &lt;code&gt;jsii&lt;/code&gt; helps to release your TypeScript CDK construct to Java, Python and C#. Here is a short tutorial about migrating a CDK construct to projen and jsii.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have provided a beginner’s step-by-step guide about &lt;a href="https://github.com/seeebiii/projen-test"&gt;getting started with projen and jsii&lt;/a&gt;. This will help you exploring typical options for projen and explains the process of publishing your CDK Construct to repositories like NPM, Maven, PyPi, and NuGet using jsii. I recommend to read it if you have no prior experience with projen or jsii.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  About projen and jsii
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/projen/projen"&gt;projen&lt;/a&gt; is a tool to write your project configuration using code instead of managing it yourself. It was created to help you writing CDK constructs. You only define your project configuration in a &lt;a href="https://github.com/seeebiii/projen-test/blob/main/.projenrc.js"&gt;.projenrc.js&lt;/a&gt; file and it will generate your project files for you. This includes a &lt;code&gt;package.json&lt;/code&gt; and other configuration files for &lt;code&gt;eslint&lt;/code&gt; or GitHub Actions. It is designed to automate all the boring project setup steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/aws/jsii"&gt;jsii&lt;/a&gt; is the technology behind the AWS CDK that allows you to write CDK Constructs in TypeScript/JavaScript and compile them to other languages like Java or Python. There’s a good &lt;a href="https://aws.amazon.com/blogs/opensource/generate-python-java-dotnet-software-libraries-from-typescript-source/"&gt;AWS blog post&lt;/a&gt; about how it works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Your Construct Project
&lt;/h2&gt;

&lt;p&gt;Let’s start to migrate your existing CDK Construct to projen. You have probably created your CDK construct using the following &lt;code&gt;cdk&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-cdk-construct
cdk init lib &lt;span class="nt"&gt;--language&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That command creates various folders and files with pre-defined defaults writing a CDK construct using TypeScript. For example, it initializes your project with a &lt;code&gt;lib&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; folder as well as an example construct file and a related test file. Finally, you can run your tests using &lt;a href="https://jestjs.io/"&gt;Jest&lt;/a&gt; with &lt;code&gt;npm run test&lt;/code&gt;. This is the basis of the next steps, even though you might have added further lib files, tests or tools like &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt; or similar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Please note&lt;/strong&gt; that you can only use &lt;code&gt;projen&lt;/code&gt; and &lt;code&gt;jsii&lt;/code&gt; with TypeScript/JavaScript as the source language at the moment. This means, you can not create a CDK construct in Java and publish it to NPM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Migrating Your CDK Construct to projen
&lt;/h2&gt;

&lt;p&gt;💡 Before you start migrating your CDK construct to projen, you might want to open this blog post about &lt;a href="https://www.matthewbonig.com/2020/10/04/converting-to-projen/"&gt;converting your CDK construct to using projen by Matthew Bonig&lt;/a&gt; in another browser tab. His article also covers some interesting facts and small errors he has experienced in the process, so they might help you as well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Before you execute any command, make sure you have a &lt;strong&gt;clean Git status&lt;/strong&gt;. This ensures that you can easily revert any undesired changes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following commands will initialize your project with &lt;code&gt;projen&lt;/code&gt;. It will create a file called &lt;code&gt;.projenrc.js&lt;/code&gt; containing a default &lt;code&gt;projen&lt;/code&gt; configuration. Then it will automatically execute this file for you to generate further files and folders based on your &lt;code&gt;projen&lt;/code&gt; configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-cdk-construct
npx projen new awscdk-construct
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After executing the commands, you’ll see lots of changes in your Git status. For example, &lt;code&gt;projen&lt;/code&gt; expects source files in &lt;code&gt;src&lt;/code&gt; whereas a CDK construct initialized via the CDK CLI expects them to live in &lt;code&gt;lib&lt;/code&gt;. Also, there will be a folder called &lt;code&gt;.projen&lt;/code&gt; containing configuration files for &lt;code&gt;projen&lt;/code&gt;. You don’t need to look into all of the new files immediately. &lt;code&gt;projen&lt;/code&gt; is managing the contents of files like GitHub Actions or TypeScript configurations based on the settings you define in &lt;code&gt;.projenrc.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updating Your Project Files with projen
&lt;/h3&gt;

&lt;p&gt;After migrating your CDK construct to &lt;code&gt;projen&lt;/code&gt;, you should always follow this process to update project files generated by &lt;code&gt;projen&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make according changes in &lt;code&gt;.projenrc.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npx projen&lt;/code&gt; and &lt;code&gt;projen&lt;/code&gt; will synthesize the changes to all project files. 💡 Hint: create an alias like &lt;code&gt;pj&lt;/code&gt; in your command line to avoid typing &lt;code&gt;npx projen&lt;/code&gt; over and over again.&lt;/li&gt;
&lt;li&gt;Never manually edit the generated files because &lt;code&gt;projen&lt;/code&gt; will overwrite them the next time!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have used tools like &lt;code&gt;eslint&lt;/code&gt; or &lt;a href="https://dependabot.com/"&gt;Dependabot&lt;/a&gt; before, you’ll probably see changes in their related files as well. If you don’t like the defaults, you can always change the settings in &lt;code&gt;.projenrc.js&lt;/code&gt;. However, you’ll probably don’t have to change that much since projen is applying common settings for eslint. I only noticed &lt;strong&gt;two changes compared to my settings&lt;/strong&gt; : include an uppercase ‘i’ (= I) in interface names and make its properties readonly. Everything else was just related to some minor style adjustments.&lt;/p&gt;

&lt;p&gt;💡 Since I don’t know all varieties of CDK construct setups, you might run into other errors after adding &lt;code&gt;projen&lt;/code&gt;. If you have any problems you can’t solve by yourself, feel free to reach out to me or send your question to the &lt;a href="https://cdk.dev/"&gt;CDK developers Slack&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Important General Settings
&lt;/h3&gt;

&lt;p&gt;Now it’s a good time to have a look at the most important settings you can set in &lt;code&gt;.projenrc.js&lt;/code&gt;. I’ll outline them below and explain them in case it’s not too obvious.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Setting&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;projectType&lt;/td&gt;
&lt;td&gt;Define if this project is a library or app. For a library (i.e. CDK construct), you should use &lt;code&gt;ProjectType.LIB&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;packageManager&lt;/td&gt;
&lt;td&gt;Define which package manager you want to use, e.g. Yarn or NPM. Set the value like &lt;code&gt;NodePackageManager.NPM&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cdkVersion&lt;/td&gt;
&lt;td&gt;With this property you are defining the CDK version you want to use for all CDK dependencies. Due to the nature of CDK, it’s important to align the numbers.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cdkDependencies&lt;/td&gt;
&lt;td&gt;Enter all the CDK dependencies that you are using in your construct. You probably had them defined in your package.json file before but now you need to add them here. Add them like &lt;code&gt;['@aws-cdk/core', '...']&lt;/code&gt;. Since you specify the CDK version with &lt;code&gt;cdkVersion&lt;/code&gt;, you don’t need to set it here.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bundledDeps&lt;/td&gt;
&lt;td&gt;List of dependencies you want to bundle with your construct. This might be necessary in case you use some constructs like &lt;code&gt;NodejsFunction&lt;/code&gt; for a Lambda function. It will build your Lambda function’s code only when the Lambda function is used in a CDK stack. And then those dependencies need to be available.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deps&lt;/td&gt;
&lt;td&gt;Any other regular dependencies that your construct is using.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;peerDeps&lt;/td&gt;
&lt;td&gt;A list of peer dependencies. &lt;code&gt;projen&lt;/code&gt; will automatically add all &lt;code&gt;@aws-cdk&lt;/code&gt; dependencies to the list of peer dependencies, so you don’t need to define them here. But you can add any other dependencies here that you’d like to have in the resulting &lt;code&gt;peerDependencies&lt;/code&gt; of the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;packageName&lt;/td&gt;
&lt;td&gt;By default, &lt;code&gt;projen&lt;/code&gt; will take the &lt;code&gt;name&lt;/code&gt; property as the name in &lt;code&gt;package.json&lt;/code&gt;. However, it might be necessary to overwrite it here.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gitignore, npmignore&lt;/td&gt;
&lt;td&gt;Should be self explanatory. You can define a list of strings matching files or folders you’d like to ignore for Git or NPM.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don’t forget to run &lt;code&gt;npx projen&lt;/code&gt; each time you make a change in &lt;code&gt;.projenrc.js&lt;/code&gt;. Otherwise &lt;code&gt;projen&lt;/code&gt; won’t synthesize the config changes to your project files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Release Settings
&lt;/h3&gt;

&lt;p&gt;You have to consider that by default &lt;code&gt;projen&lt;/code&gt; assumes you want to publish your CDK construct to NPM. Hence, it sets up GitHub Actions that perform the relevant tasks for you, like bundling, running the tests and releasing the artifact. If you want to skip this for now, consider adjusting the following settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Setting&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;releaseBranches&lt;/td&gt;
&lt;td&gt;A list of branch names. The default is &lt;code&gt;['main']&lt;/code&gt; but you can adjust it to whatever branches you need. If you set this to an empty array, then you can only trigger a release by manually starting the release workflow (in case you enabled to add a release workflow, see below).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;releaseEveryCommit&lt;/td&gt;
&lt;td&gt;If set to &lt;code&gt;true&lt;/code&gt; and a commit is added on any of the branches defined in &lt;code&gt;releaseBranches&lt;/code&gt;, then a release is triggered.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;releaseSchedule&lt;/td&gt;
&lt;td&gt;Optional: cron expression to regularly release a new version.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;releaseToNpm&lt;/td&gt;
&lt;td&gt;If a new version should be released to NPM using GitHub Actions.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;releaseWorkflow&lt;/td&gt;
&lt;td&gt;If you want to have a release workflow using GitHub Actions.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Again, don’t forget to run &lt;code&gt;npx projen&lt;/code&gt; to update your project files after changing the &lt;code&gt;projen&lt;/code&gt; settings in &lt;code&gt;.projenrc.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Location of Lambda Function Code
&lt;/h3&gt;

&lt;p&gt;In case you are creating a Lambda function in your CDK construct, you might wonder where you should put your Lambda function code and how you bundle it. When using &lt;code&gt;projen&lt;/code&gt;, I’d say a good approach is to keep all the Lambda function code in a subfolder next to your CDK construct source files. For example, the code could go into &lt;code&gt;src/lambda&lt;/code&gt;. This ensures that &lt;code&gt;projen&lt;/code&gt; picks up the files and includes them in the artifact that’s being released to NPM. You can read my other blog post if you want to know more ways about &lt;a href="https://www.sebastianhesse.de/2021/01/16/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct/"&gt;how to bundle your Lambda function code in a CDK construct&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Your Construct
&lt;/h3&gt;

&lt;p&gt;Now that you have finally adjusted the necessary &lt;code&gt;projen&lt;/code&gt; settings and fixed any code or linting issues, you can verify that your code compiles. You can use commands like &lt;code&gt;npm run build&lt;/code&gt; or &lt;code&gt;npm run test&lt;/code&gt; to verify your code. (Use &lt;code&gt;Yarn&lt;/code&gt; instead if you kept &lt;code&gt;projen&lt;/code&gt;‘s default setting of &lt;code&gt;packageManager&lt;/code&gt;) Is your code compiling? Great! If not, did you forget anything or did I miss to cover anything here? Let me know about it!&lt;/p&gt;

&lt;p&gt;After a green build, you are ready to commit your changes and push them to your remote Git repository. Then, the GitHub actions configured under &lt;code&gt;.github/actions&lt;/code&gt; will trigger and build (+ release) your CDK construct 🚀&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Build or Workflow Steps
&lt;/h3&gt;

&lt;p&gt;Before migrating your CDK construct to &lt;code&gt;projen&lt;/code&gt;, you probably had some custom scripts or commands in your project. For example, you prepared certain things for a Lambda function or your CDK construct in general. With &lt;code&gt;projen&lt;/code&gt; you can add custom build and workflow steps as well. Here is how you can do it in &lt;code&gt;.projenrc.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;project&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;AwsCdkConstructLibrary&lt;/span&gt;&lt;span class="p"&gt;({...});&lt;/span&gt;

&lt;span class="c1"&gt;// add a build step:&lt;/span&gt;
&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;buildTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;echo "Hello World"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// add a job to the GitHub Action file of release.yml:&lt;/span&gt;
&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;releaseWorkflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addJobs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;example&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Example Job&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;runs-on&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ubuntu-latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;steps&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;As soon as update the project files by running &lt;code&gt;npx projen&lt;/code&gt; again, you’ll see changes in &lt;code&gt;.projen/tasks.json&lt;/code&gt; and &lt;code&gt;.github/actions/release.yml&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing to Multiple Repositories Using jsii
&lt;/h2&gt;

&lt;p&gt;After you have finally migrated your code, it’s time to add some magic to your CDK construct. The magic comes by a combination of &lt;code&gt;projen&lt;/code&gt; and &lt;code&gt;jsii&lt;/code&gt;. Their biggest advantage is that you can make your CDK construct available not only to NPM but also Maven, PyPi and NuGet by just setting a few settings.&lt;/p&gt;

&lt;p&gt;As described above, &lt;code&gt;projen&lt;/code&gt; provides a few release settings. Use them to publish your CDK construct to NPM. If you want to publish your CDK construct to Maven, PyPi or NuGet, then consider the following settings:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Setting&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Repository&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;publishToMaven&lt;/td&gt;
&lt;td&gt;Maven&lt;/td&gt;
&lt;td&gt;Allows you to configure the Java package, group id and artifact id.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;publishToPypi&lt;/td&gt;
&lt;td&gt;PyPi&lt;/td&gt;
&lt;td&gt;Allows you to configure the dist name and module.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;publishToNuget&lt;/td&gt;
&lt;td&gt;NuGet&lt;/td&gt;
&lt;td&gt;Allows you to configure the namespace and package id.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Enabling these settings (and running &lt;code&gt;npx projen&lt;/code&gt; again 😉) will create appropriate steps in the &lt;code&gt;release.yml&lt;/code&gt; GitHub Action. You can find detailed steps for each repository in my guide about &lt;a href="https://github.com/seeebiii/projen-test#publishing-to-different-repositories"&gt;creating a CDK construct using projen and jsii on GitHub&lt;/a&gt;. Besides that, you don’t need to do anything. Just commit your changes and wait for the magic to happen!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--devVdXeA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/02/successful-projen-action-run-1024x516.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--devVdXeA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/02/successful-projen-action-run-1024x516.png" alt="Successful CDK construct release using projen and jsii."&gt;&lt;/a&gt;A successful release using projen and jsii. Example taken from &lt;a href="https://github.com/seeebiii/projen-test"&gt;projen-test&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;I hope you were successful in migrating your existing CDK construct to &lt;code&gt;projen&lt;/code&gt; and &lt;code&gt;jsii&lt;/code&gt;. In my opinion it offers a really good way to manage your project and hide quite a few complicated steps. Also, shipping to various repositories works like a charm!&lt;/p&gt;

&lt;p&gt;Are you running into any errors? Comment below and let me see if I can help you 😊&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.sebastianhesse.de/2021/03/01/migrating-a-cdk-construct-to-projen-and-jsii/"&gt;Migrating a CDK Construct to projen and jsii&lt;/a&gt; was first published on &lt;a href="https://www.sebastianhesse.de"&gt;Sebastian Hesse - Software Engineer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awscdk</category>
      <category>cdkconstruct</category>
      <category>projen</category>
    </item>
    <item>
      <title>Using Spring Boot On AWS Lambda: Clever or Dumb?</title>
      <dc:creator>Sebastian Hesse</dc:creator>
      <pubDate>Sun, 14 Feb 2021 13:00:00 +0000</pubDate>
      <link>https://dev.to/seeebiii/using-spring-boot-on-aws-lambda-clever-or-dumb-3350</link>
      <guid>https://dev.to/seeebiii/using-spring-boot-on-aws-lambda-clever-or-dumb-3350</guid>
      <description>&lt;p&gt;I often notice people wondering if and how it’s possible to run Spring Boot on AWS Lambda Functions. I understand this because I know developers in the Java ecosystem often use the Spring Framework. And since more and more people built Lambda functions using Java, the question will be asked at some point. It’s definitely possible to run Spring Boot on AWS Lambda. However, if you think about it a second time, you’ll find many reasons why it is a bad idea. This blog post discusses the advantages and disadvantages of running Spring Boot on AWS Lambda on a conceptual level. And in case I won’t convince you, I’ll at least provide you some hints to overcome the disadvantages.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are you using Java or even Spring (Boot) on AWS Lambda? I have used it in production systems and I believe it’s good for certain use cases like background data processing. What is your use case? Do you try to overcome the disadvantages and if so, how? Just add a comment below or mention me on &lt;a href="https://twitter.com/seeebiii"&gt;Twitter&lt;/a&gt; 👍&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Some Context Around Spring Boot And AWS Lambda
&lt;/h2&gt;

&lt;p&gt;As you all probably know (&lt;a href="https://www.sebastianhesse.de/2019/07/21/going-serverless-why-and-how-1/"&gt;if not, then read here&lt;/a&gt;), AWS Lambda and similar Function-as-a-Service (FaaS) solutions let you run code in the cloud without managing any of the underlying infrastructure. This enables a cloud provider to better scale your code because these functions are a small enough to be started on demand. Although Java is one of the supported languages with a &lt;a href="https://blog.symphonia.io/posts/2020-06-30_analyzing_cold_start_latency_of_aws_lambda"&gt;slower initial start time (= cold start)&lt;/a&gt;, it can still be a good choice for AWS Lambda because of its big ecosystem that grew over all the years.&lt;/p&gt;

&lt;p&gt;For example, the Spring Framework is one of the most popular Java frameworks. It collects best practices working with different things like a database and HTTP. Eventually Spring Boot made it even simpler to connect the different Spring modules together. A typical use case for Spring Boot is to build a microservice that can handle HTTP requests. You just define a &lt;code&gt;@Controller&lt;/code&gt; , give it a &lt;code&gt;@RequestMapping&lt;/code&gt; and have your first endpoint ready that can react to an HTTP request (read &lt;a href="https://www.baeldung.com/building-a-restful-web-service-with-spring-and-java-based-configuration"&gt;this blog post&lt;/a&gt; as an example).&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting AWS Lambda And Spring Boot
&lt;/h2&gt;

&lt;p&gt;Unfortunately this setup won’t work out of the box if you’re running this code on AWS Lambda. The reason is that AWS Lambda is using an event-based mechanism. An event can consist of any kind of data that is serializable. However, you won’t be able to receive HTTP requests from within your Lambda function. (Of course you can make HTTP requests to other services but not the other way around). This is the reason why you need a service or application in front of your AWS Lambda function. Such a service can receive HTTP requests and forward them to your Lambda function. A typical example is an &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html"&gt;AWS API Gateway&lt;/a&gt;. But you can also &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html"&gt;use an AWS Application Load Balancer&lt;/a&gt;. These services keep the HTTP connection open until your Lambda function responds to the HTTP event. Without this setup you won’t receive any HTTP events in your Lambda function.&lt;/p&gt;

&lt;p&gt;In order to start using Spring Boot on AWS Lambda, I suggest you to checkout the different helpers in &lt;a href="https://github.com/awslabs/aws-serverless-java-container"&gt;aws-serverless-java-container&lt;/a&gt;. This is a collection of Java classes that help you using typical Java frameworks on AWS Lambda, including Spring. They already provide you with the necessary glue code to connect the AWS Lambda handler with Spring Boot. There are also other (but similar) ways to ingrate the Spring Framework like using &lt;a href="https://rieckpil.de/java-aws-lambda-with-spring-cloud-function/"&gt;Spring Cloud Functions on AWS Lambda&lt;/a&gt;. In the end, the architecture looks similar to this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_IVWX7Wa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/01/spring-boot-on-aws-lambda-architecture-2-1024x576.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_IVWX7Wa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/01/spring-boot-on-aws-lambda-architecture-2-1024x576.jpeg" alt=""&gt;&lt;/a&gt;Architecture how an HTTP request is received as an event from API Gateway to Spring Boot in your Lambda function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages
&lt;/h2&gt;

&lt;p&gt;Let’s discuss the advantages of this approach because there are definitely a few. First, you can setup an API Gateway to forward all HTTP requests as events using a proxy integration with AWS Lambda. This basically enables you to configure a wildcard path in API Gateway and lets your Spring Boot app handle all the internal routing. Using this approach, you and your team can continue using Spring Boot like you’re used to. Second, as soon as one Lambda function instance has initialized the Spring Boot container, this function will respond in a consistent way. The performance is as expected from Java, at least that’s my experience with Java Lambda functions.&lt;/p&gt;

&lt;p&gt;However, the most obvious advantage is that you don’t have to manage the underlying instances with AWS Lambda. But this advantage has a catch: You need to ensure you are not storing any session data (or similar) inside your Spring Boot app. Remember that you should keep Lambda functions stateless, otherwise scaling becomes harder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disadvantages
&lt;/h2&gt;

&lt;p&gt;You might have recognized already that using API Gateway + AWS Lambda + Spring Boot is duplicating responsibilities. In the world before Serverless you would have used Spring Boot alone to handle HTTP requests and implement your business logic. Now the combination of API Gateway and AWS Lambda is replacing it. Even more than that, it enables you to have better scalability because of this separation of concerns from an operational aspect. This means you can put a big question mark on the idea of running Spring Boot inside AWS Lambda.&lt;/p&gt;

&lt;p&gt;But not only duplicating responsibilities is a bad sign. Also the fact that you add unnecessary complexity to integrate Spring Boot with AWS Lambda should make you think twice. In the end, all these wrapper and helper classes introduce more potential for bugs. And together with Spring Boot they also have a bad effect on the cold start of your Lambda functions of course. Apart from that, Spring Boot own it’s own is even too slow to start quickly like it’s expected from Lambda functions. This means, you’ll have massive spikes in your response times when a new Lambda function instance is started.&lt;/p&gt;

&lt;p&gt;Although not worrying about the instances of your Lambda function sounds appealing, you have to remember that you can not control how many you’ll have. This can have negative consequences if you’re e.g. making requests to an SQL database in direct response to external events. You might run out of database connections quickly if a spike hits your Lambda function because AWS Lambda spins up more and more instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Personal Opinion And Experience
&lt;/h2&gt;

&lt;p&gt;I (and many other Serverless developers) recommend to keep AWS Lambda functions simple and small. If you follow this recommendation, then your functions are a lot easier to scale. If you instead build another monolith using Spring Boot on top of AWS Lambda, then you are doing it wrong. Keep that in mind while developing AWS Lambda functions with Java but especially if you include Spring as well.&lt;/p&gt;

&lt;p&gt;Having said that, I have successfully used Spring in Java Lambda functions in previous projects. I enjoyed running them in the background doing some data processing. However, I’m not convinced that they are a good choice for “customer facing” endpoints like a REST API. The only exception is if you keep a minimum of Lambda instances running. But then you can question if AWS Lambda is the right choice for your Spring Boot app. In such a case I’d rather suggest you to use traditional EC2 instances or ECS.&lt;/p&gt;

&lt;p&gt;If you still want to use Sprint Boot on AWS Lambda, then you should consider some recent developments. For example, you might have heard of GraalVM or Quarkus. You can use it to &lt;a href="https://aws.amazon.com/blogs/architecture/field-notes-optimize-your-java-application-for-aws-lambda-with-quarkus/"&gt;run Java native images on AWS Lambda&lt;/a&gt; by providing a custom runtime. Also, &lt;a href="https://github.com/spring-projects/spring-framework/wiki/GraalVM-native-image-support"&gt;Spring is adding support for GraalVM&lt;/a&gt; native images. I can recommend looking into the Slides of &lt;a href="https://www.slideshare.net/VadymKazulkin/adopting-java-for-the-serverless-world-at-serverless-meetup-new-york-and-boston"&gt;Vadym’s talk “Adopting Java for the Serverless world”&lt;/a&gt; that goes into more detail.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.sebastianhesse.de/2021/02/14/using-spring-boot-on-aws-lambda-clever-or-dumb/"&gt;Using Spring Boot On AWS Lambda: Clever or Dumb?&lt;/a&gt; was first published on &lt;a href="https://www.sebastianhesse.de"&gt;Sebastian Hesse - Software Engineer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>development</category>
      <category>java</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Serverless Sending and Receiving E-Mails, the CDK Way</title>
      <dc:creator>Sebastian Hesse</dc:creator>
      <pubDate>Sun, 31 Jan 2021 15:00:00 +0000</pubDate>
      <link>https://dev.to/seeebiii/serverless-sending-and-receiving-e-mails-the-cdk-way-2l79</link>
      <guid>https://dev.to/seeebiii/serverless-sending-and-receiving-e-mails-the-cdk-way-2l79</guid>
      <description>&lt;p&gt;Serverless sending and receiving e-mails using AWS is not fun in my opinion. AWS offers Simple Email Service (SES) to achieve this. But the UI and also Infrastructure as Code (IaC) support is lacking. You often need to manually change settings which is error prone. When I recently built another landing page for myself, I was repeating the same steps as for the previous page. It bothered me why there’s no easy automation that’s doing it for me. This is what I’m presenting to you today: My first AWS CDK Constructs to send and receive e-mails.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can find the source code of the AWS CDK Constructs in the &lt;a href="https://github.com/seeebiii/ses-email-forwarding"&gt;ses-email-forwarding GitHub repository&lt;/a&gt;. Besides that, I also made &lt;a href="https://github.com/seeebiii/ses-verify-identities"&gt;ses-verify-identities&lt;/a&gt; available as separate AWS CDK Constructs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Setup Steps With AWS SES
&lt;/h2&gt;

&lt;p&gt;Have you ever built your own landing page with its own domain? Or have you ever wanted to use another alias for receiving e-mails? Or did you just want to use an e-mail address for a domain you own without the hassle of setting up your own mail server and instead forward the mails to your existing inbox? If yes, I have some great news for you! 😊 &lt;/p&gt;

&lt;p&gt;Initially, I have used a library called &lt;a href="https://github.com/arithmetric/aws-lambda-ses-forwarder"&gt;aws-lambda-ses-forwarder&lt;/a&gt; for serverless sending and receiving e-mails. I always had to follow these manual steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Setup AWS SES and &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-getting-started-verify.html"&gt;verify my domain&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Configure &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-getting-started-receipt-rule.html"&gt;receipt rules&lt;/a&gt; for the different e-mail addresses.&lt;/li&gt;
&lt;li&gt;Then &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/receiving-email-action-lambda.html"&gt;setup a Lambda function SES Action&lt;/a&gt; that forwards all my e-mails from SES to a Gmail address.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/send-email-smtp.html"&gt;Configure SMTP for AWS SES&lt;/a&gt; and setup Gmail to send e-mails with my verified domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My new AWS CDK constructs below automate the first three setup steps for AWS SES. They even allow you to automatically verify your e-mail addresses or domains within SES (if you’re using Route53). Just deploy the constructs in your AWS CDK stack and you’re ready to go. You only need to create SMTP credentials for AWS SES and setup your settings with Gmail (or other providers). Let’s see how it’s working ⬇&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS CDK Constructs to the Rescue
&lt;/h2&gt;

&lt;p&gt;The best way to show how it’s working is by showing you a few lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {
  enableRuleSet: true,
  emailForwardingProps: [{
    domainName: 'example.org',
    verifyDomain: true,
    fromPrefix: 'noreply',
    emailMappings: [{
      receivePrefix: 'hello',
      targetEmails: ['whatever+hello@provider.com']
    }]
  }]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is using the &lt;code&gt;EmailForwardingRuleSet&lt;/code&gt; construct to configure everything. Let me quickly the most important things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can configure to automatically enable the rule set because you can only have on active rule set in AWS SES.&lt;/li&gt;
&lt;li&gt;You define e-mail forwarding rules by specifying your domain name and the e-mail mappings. E-mail mappings define a &lt;code&gt;receivePrefix&lt;/code&gt; which is your e-mail alias and a list of &lt;code&gt;targetEmails&lt;/code&gt;. All e-mails to your alias/prefix are forwarded to these target e-mails. The forwarded e-mails have a prefix of &lt;code&gt;noreply@example.org&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the domain is managed by Route53, then you can automatically verify the domain. This setting will configure some custom resources to validate the domains.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it already. You can further extend the configuration of course. For example, you can add more e-mail mappings for various aliases/prefixes. Or you can add another domain with individual e-mail mappings. It’s up to you 👍&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy Your AWS CDK Stack
&lt;/h3&gt;

&lt;p&gt;Now you just need to put everything into an AWS CDK stack. Before you start, initialize a new CDK stack and install my CDK constructs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk init app --language=typescript
npm i -D @seeebiii/ses-email-forwarding
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, create a new file that contains your stack. It can look similar to the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const app = new cdk.App();

class EmailForwardingSetupStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    new EmailForwardingRuleSet(this, 'EmailForwardingRuleSet', {
      // define your config here
    });
  }
}

new EmailForwardingSetupStack(app, 'EmailForwardingSetupStack', {
  env: {
    account: '&amp;lt;account-id&amp;gt;',
    region: '&amp;lt;region&amp;gt;'
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, you use the &lt;code&gt;cdk deploy&lt;/code&gt; command to deploy the stack. Everything else like verifying your domains and setting up SES will be done for you. Now you can start with serverless sending and receiving e-mails!&lt;/p&gt;

&lt;p&gt;In the end, you’ll have this architecture for serverless receiving e-mails using AWS SES:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2A-7K2gN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/01/aws-ses-receive-emails-serverless-1024x576.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2A-7K2gN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.sebastianhesse.de/wp-content/uploads/2021/01/aws-ses-receive-emails-serverless-1024x576.jpeg" alt="Architecture how an email is received and forwarded in a serverless way."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All &lt;strong&gt;1.) incoming e-mails&lt;/strong&gt; are handled by SES. SES will &lt;strong&gt;2.) move them to S3&lt;/strong&gt; and afterwards &lt;strong&gt;3.) invokes a Lambda function&lt;/strong&gt;. This Lambda function &lt;strong&gt;4.) loads the e-mail&lt;/strong&gt; from S3 and &lt;strong&gt;5.) forwards it&lt;/strong&gt; to either Gmail or another target e-mail address. In case you are interested, I have written another blog post about how you can &lt;a href="https://www.sebastianhesse.de/2021/01/16/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct/"&gt;include AWS Lambda functions inside a CDK construct&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending E-Mails with AWS SES
&lt;/h2&gt;

&lt;p&gt;Unfortunately this is the remaining step that can’t be automated. Once the above CDK stack is deployed to your AWS Account, you need to &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/smtp-credentials.html?icmpid=docs_ses_console"&gt;create SMTP credentials in AWS SES&lt;/a&gt;. These credentials allow you to send e-mails from any e-mail application or provider like Gmail. However, this will only work if you have verified your sender domain in AWS SES. Otherwise your e-mails will only be sent to verified e-mail addresses to avoid that you’re sending spam through AWS SES. If you would like to verify the target e-mail addresses with the CDK construct, just use the setting &lt;code&gt;verifyTargetEmailAddresses&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Solutions
&lt;/h2&gt;

&lt;p&gt;You may have already asked yourself if there are really no other existing solutions to this problem. I can assure you there are other solutions for sending and receiving e-mails in a serverless way. However, they did not solve my problem as I expected or I’ve discovered them too late. Here are a few alternatives now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/arithmetric/aws-lambda-ses-forwarder"&gt;aws-lambda-ses-forwarder&lt;/a&gt; -&amp;gt; An NPM package to be used in a Lambda function. It can be triggered by an SES event and forwards e-mails to e.g. Gmail. Unfortunately, only using this library in a Lambda function requires you to setup all the necessary steps by hand. Besides that it offers a really flexible configuration for forwarding e-mails.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pypi.org/project/aws-cfn-ses-domain/"&gt;aws-cfn-ses-domain&lt;/a&gt; -&amp;gt; CloudFormation custom resources for domain and e-mail verification. This helps if you’re writing your infrastructure in CloudFormation but it’s missing some other pieces, like e-mail handling in general.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/0x4447/0x4447_product_s3_email"&gt;S3 Email&lt;/a&gt; -&amp;gt; A combination of S3 and SES where e-mails are stored on S3 and S3 is used as the “e-mail interface”.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://simplelogin.io/"&gt;simplelogin.io&lt;/a&gt; -&amp;gt; An SaaS app to setup various e-mail aliases. You can also &lt;a href="https://github.com/simple-login/app"&gt;deploy it yourself on AWS&lt;/a&gt; and connect the stack with SES. It’s probably the most user friendly way to solve the user cases I’ve mentioned above. However, I only discovered it after I had implemented most of the things. Also, the self-hosting steps looked like too much work is necessary.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://improvmx.com/"&gt;improvmx.com&lt;/a&gt; -&amp;gt; An SaaS app similar to simplelogin.io. It can create e-mail aliases for you and forward the e-mails to another address like Gmail. It’s pretty similar to what my CDK constructs can do for you. Like the other one, I only discovered this solution after I had implemented most of the things. Unfortunately, there’s no self-hosting version available as far as I know.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I’ve learned a lot on the way of building my first AWS CDK construct! On tricky part was to &lt;a href="https://www.sebastianhesse.de/2021/01/16/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct/"&gt;bundle a Lambda function inside the AWS CDK Construct&lt;/a&gt; as mentioned above. I’m really happy with the result because I can easily extend the settings for new landing pages or other email aliases. What do you think about my solution? Let me know in the comments below or mention me on &lt;a href="https://twitter.com/seeebiii"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.sebastianhesse.de/2021/01/31/serverless-sending-and-receiving-e-mails-the-cdk-way/"&gt;Serverless Sending and Receiving E-Mails, the CDK Way&lt;/a&gt; was first published on &lt;a href="https://www.sebastianhesse.de"&gt;Sebastian Hesse - Software Engineer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>javascript</category>
      <category>serverless</category>
    </item>
    <item>
      <title>5 Ways To Bundle a Lambda Function Within an AWS CDK Construct</title>
      <dc:creator>Sebastian Hesse</dc:creator>
      <pubDate>Sat, 16 Jan 2021 12:32:38 +0000</pubDate>
      <link>https://dev.to/seeebiii/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct-1e28</link>
      <guid>https://dev.to/seeebiii/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct-1e28</guid>
      <description>&lt;p&gt;Have you ever tried to publish a CDK construct that was using a Lambda function, for example to create a custom resource or provide a REST API endpoint? It’s relatively easy to publish your construct if your Lambda function is just using the AWS SDK. But it gets more complicated as soon as other dependencies are involved as well. This post will present you five different ways to bundle your Lambda function within a CDK construct and tells you about the advantages and disadvantages of each option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem Context
&lt;/h2&gt;

&lt;p&gt;Recently I started digging more into the &lt;a href="https://aws.amazon.com/cdk/" rel="noopener noreferrer"&gt;AWS CDK&lt;/a&gt; world and wanted to build a simple single page application. I had some special requirement for which I couldn’t find an existing CDK construct available in TypeScript. So I thought let’s create it myself and publish it later to NPM. I wanted to include a Lambda function in this CDK construct that was using an external dependency apart from the AWS SDK. &lt;strong&gt;The problem is&lt;/strong&gt; that if you require other dependencies in an AWS Lambda function, you need to bundle them with your function (the AWS SDK is always available for Node.js runtimes). This means, you have to create an artifact that includes all required dependencies. However, I wanted to avoid that my resulting CDK construct package gets too big. I had some ideas in my mind but also asked &lt;a href="https://twitter.com/seeebiii/status/1348716172649361408?s=20" rel="noopener noreferrer"&gt;CDK experts on Twitter&lt;/a&gt; for their opinion and experiences. Below are the results of my ideas and their suggestions!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1348716172649361408-996" src="https://platform.twitter.com/embed/Tweet.html?id=1348716172649361408"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1348716172649361408-996');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1348716172649361408&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;You have another idea how to &lt;strong&gt;include a Lambda function in a CDK construct&lt;/strong&gt;? Please comment below ⬇️ or let me know &lt;a href="https://twitter.com/seeebiii" rel="noopener noreferrer"&gt;via Twitter @seeebiii&lt;/a&gt;. If you’re curious about developing AWS Lambda functions in general, I can recommend you my article about &lt;a href="https://www.sebastianhesse.de/2020/03/31/going-serverless-why-and-how-2/" rel="noopener noreferrer"&gt;best practices developing AWS Lambda functions&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inline Code in CDK Construct
&lt;/h2&gt;

&lt;p&gt;The easiest solution is to write some inline code within the CDK code. It usually looks like this when using the &lt;code&gt;Function&lt;/code&gt; construct from the &lt;code&gt;@aws-cdk/aws-lambda&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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="s1"&gt;MyFunction&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;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;code&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="nf"&gt;fromInline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    exports.handler = async (event) =&amp;gt; {
      console.log('event: ', event)
    };
  `&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;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODEJS_12_X&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will create a Lambda function with a very basic implementation. You can of course extend it further. However, you are a bit limited in terms of which dependencies you can include. For example, you can only refer to external dependencies like the AWS SDK and regular Node.js modules like &lt;code&gt;path&lt;/code&gt; of &lt;code&gt;fs&lt;/code&gt;. Also, this approach only works for runtimes that interpret text files, like Python or Node.js. It does not work for languages like Java.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Quick and easy way to write a Lambda function&lt;/li&gt;
&lt;li&gt;No extra bundle steps necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You are very limited what your function can do&lt;/li&gt;
&lt;li&gt;No IDE support while writing your code&lt;/li&gt;
&lt;li&gt;No testing possible, only manual tests&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Separate File(s) in CDK Construct
&lt;/h2&gt;

&lt;p&gt;Instead of providing inline code, you can also move your Lambda function code outside of the CDK code into a separate file. Then, you just link to your file from the CDK construct your using. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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="s1"&gt;MyFunction&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;runtime&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_12_X&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="s1"&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;code&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="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/lambda`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;code&lt;/code&gt; property is referencing an external asset which points to the file of your Lambda function. It assumes the following folder structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;root/
 - my-stack.js
 - lambda/
   - index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When deploying a stack with this function code, the CDK will simply take the &lt;code&gt;index&lt;/code&gt; file of your Lambda function and use it as your Lambda function’s code. You can do something similar using other runtimes like Java or Python. Just reference the appropriate artifact like a JAR or Python file. Although this approach is much more preferred than writing inline code, it still has the drawback that you can not simply include other dependencies apart from the AWS SDK, at least for Node.js. You could of course zip your &lt;code&gt;index.js&lt;/code&gt; file together with your &lt;code&gt;node_modules&lt;/code&gt; folder and use that as your artifact. However, this approach is &lt;strong&gt;not recommended&lt;/strong&gt; because it unnecessarily slows down your Lambda function due to a bigger artifact size. You’re just carrying around code which you’re not using.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Keep CDK stack code and Lambda function code separated&lt;/li&gt;
&lt;li&gt;You can test your Lambda function’s code using automated tests&lt;/li&gt;
&lt;li&gt;IDE support while writing your Lambda function’s code&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;External dependencies (apart from AWS SDK) not supported&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bundle Lambda Function Before Publishing
&lt;/h2&gt;

&lt;p&gt;If you want to use other external dependencies, you need to make sure that those dependencies are available when your Lambda function is executed. Therefore, the next logical step is to bundle your Lambda function’s code and generate a code artifact with all the dependencies included. This artifact is used by your CDK construct and in the end used by the users of your construct. In your CDK construct you still use the same &lt;code&gt;Function&lt;/code&gt; definition as above where you include the code asset. However, you have to make sure to bundle your code before you publish your CDK construct to any registry like NPM. For example, if you’re writing a TypeScript Lambda function, you can use &lt;a href="https://esbuild.github.io/" rel="noopener noreferrer"&gt;esbuild&lt;/a&gt; (or webpack or similar) to compile and bundle it to “native” Node.js code that your Lambda function understands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;esbuild lambda/index.ts &lt;span class="nt"&gt;--bundle&lt;/span&gt; &lt;span class="nt"&gt;--platform&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;node &lt;span class="nt"&gt;--target&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;node12 &lt;span class="nt"&gt;--external&lt;/span&gt;:aws-sdk &lt;span class="nt"&gt;--outfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;lambda/build/index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates an &lt;code&gt;index.js&lt;/code&gt; file with all dependencies included, except the AWS SDK since this is already provided by the Lambda runtime. If you want to speed up your Lambda function even more, you can append &lt;code&gt;--minify&lt;/code&gt; to use minification and reduce the output size. Here the output file is created under &lt;code&gt;lambda/build&lt;/code&gt;, so take care to adjust the &lt;code&gt;Function&lt;/code&gt; definition. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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="s1"&gt;MyFunction&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;runtime&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_12_X&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="s1"&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;code&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="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/lambda/build`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to include the Lambda function’s code in your published CDK construct, consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure the &lt;code&gt;lambda/build&lt;/code&gt; folder is not ignored by NPM (this is usually configured in &lt;code&gt;.npmignore&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Before publishing the construct, you have to bundle the Lambda function first – otherwise your published construct is missing the code for your Lambda function&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Everything from the previous section about having separate files&lt;/li&gt;
&lt;li&gt;You don’t make any assumptions about the environment of the users that use your construct (will be important in the following sections)&lt;/li&gt;
&lt;li&gt;You throw out all unnecessary code by only bundling the relevant code and maybe even minifying it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;It takes another build step and slightly increases the size of your CDK construct&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bundle Lambda Function Before Deploying
&lt;/h2&gt;

&lt;p&gt;Instead of bundling the code before publishing your CDK construct, you can also bundle your Lambda function code before the construct is deployed to AWS. The AWS CDK provides a construct for Node.js Lambda functions called &lt;code&gt;NodejsFunction&lt;/code&gt; from the &lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-lambda-nodejs-readme.html" rel="noopener noreferrer"&gt;&lt;code&gt;@aws-cdk/aws-lambda-nodejs&lt;/code&gt; package&lt;/a&gt;. This construct will build the Lambda function as soon as your CDK construct is deployed within a stack. The &lt;code&gt;NodejsFunction&lt;/code&gt; construct is using esbuild to do that or a Docker container if esbuild is not available (&lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda-nodejs.NodejsFunction.html" rel="noopener noreferrer"&gt;read more about it in the documentation&lt;/a&gt;). Using it in your construct is similar to how you define a regular &lt;code&gt;Function&lt;/code&gt; – however, it already defines some useful defaults. An example definition can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;NodejsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyFunction&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;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/lambda/index.js`&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it’s pretty simple and short. Unfortunately the big disadvantage is that you make assumptions about the environment where your construct is deployed. If they don’t have esbuild or Docker available, it won’t work. Therefore it only makes sense to use &lt;code&gt;NodejsFunction&lt;/code&gt; in an constructs where you control the environment or if you let your users know about this requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Everything from the previous section about having separate files&lt;/li&gt;
&lt;li&gt;You throw out all unnecessary code by only bundling the relevant code and maybe even minifying it&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You make assumptions about the environment of the users of your construct&lt;/li&gt;
&lt;li&gt;It takes another build step and slightly increases the size of your CDK construct&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Publish Lambda Function to Serverless Application Repository or Using Docker
&lt;/h2&gt;

&lt;p&gt;A completely different option compared to the ones above is to use the Serverless Application Repository. It’s a repository for serverless application that you can build and &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-template-publishing-applications.html" rel="noopener noreferrer"&gt;publish to AWS using the SAM CLI&lt;/a&gt;. Then you can use this application in other stacks using the &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-application.html" rel="noopener noreferrer"&gt;CloudFormation SAM type &lt;code&gt;AWS::Serverless::Application&lt;/code&gt;&lt;/a&gt;. The CDK equivalent is &lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-sam.CfnApplication.html" rel="noopener noreferrer"&gt;CfnApplication&lt;/a&gt; from the &lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-sam-readme.html" rel="noopener noreferrer"&gt;@aws-cdk/aws-sam&lt;/a&gt; package. Since those applications can be made public to everyone, you have a neat way to host your Lambda function outside of your CDK construct, i.e. without bundling it inside your CDK construct. You could even &lt;a href="https://docs.aws.amazon.com/serverlessrepo/latest/devguide/sharing-lambda-layers.html" rel="noopener noreferrer"&gt;share your AWS Lambda Layer in the same way&lt;/a&gt; and reference that instead of a full serverless application (see &lt;a href="https://levelup.gitconnected.com/blog-md-9bd47be8b3ad" rel="noopener noreferrer"&gt;how to use Layers in AWS CDK here&lt;/a&gt;). This has the advantage that you can still use the &lt;code&gt;Function&lt;/code&gt; construct as explained above and just add a &lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-lambda.LayerVersion.html" rel="noopener noreferrer"&gt;&lt;code&gt;LayerVersion&lt;/code&gt; construct&lt;/a&gt;. Similarly, you can &lt;a href="https://aws.amazon.com/blogs/compute/using-container-image-support-for-aws-lambda-with-aws-sam/" rel="noopener noreferrer"&gt;publish your Lambda function as a container nowadays&lt;/a&gt; and reference that in your CDK construct. The CDK provides a &lt;code&gt;DockerImageFunction&lt;/code&gt; for this case.&lt;/p&gt;

&lt;p&gt;Although these options sound like a good idea because you are much more flexible in how your Lambda function is built, the solution has two disadvantages: First, you are referencing an unknown external stack or dependency that you should make your users aware of so they can verify it. Second, it adds much more complexity than often necessary. Especially if you’re using a Node.js runtime, none of these step should be necessary for bundling a Lambda function within your CDK construct. It’s much easier to use one of the other options above.&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Separation of concerns&lt;/li&gt;
&lt;li&gt;Flexibility of which dependencies you need and how you provide them&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More complexity&lt;/li&gt;
&lt;li&gt;Potential concerns by users&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;In most cases having separate files is totally enough. Especially if you just use the AWS SDK in your Lambda function, there’s often no need to over-optimize your code. However, as soon as you use other external dependencies, you have to do more to bundle a Lambda function within a CDK construct. My recommended approach is to bundle your Lambda function &lt;strong&gt;before&lt;/strong&gt; you publish your CDK construct. Then, in your CDK construct just use the bundled artifact. As mentioned, the advantage is that you don’t make any assumptions about the (build) environments that the users of your CDK constructs have.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://www.sebastianhesse.de/2021/01/16/5-ways-to-bundle-a-lambda-function-within-an-aws-cdk-construct/" rel="noopener noreferrer"&gt;5 Ways To Bundle a Lambda Function Within an AWS CDK Construct&lt;/a&gt; was first published on &lt;a href="https://www.sebastianhesse.de" rel="noopener noreferrer"&gt;Sebastian Hesse - Software Engineer&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
      <category>awslambda</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
