<?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: Igor Soroka</title>
    <description>The latest articles on DEV Community by Igor Soroka (@grenguar).</description>
    <link>https://dev.to/grenguar</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%2F603390%2F32056967-ff3d-4afc-8bc5-9e9ef9001237.jpeg</url>
      <title>DEV Community: Igor Soroka</title>
      <link>https://dev.to/grenguar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/grenguar"/>
    <language>en</language>
    <item>
      <title>AWS Certification Exam Preparation. An Ultimate Guide</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Tue, 14 Mar 2023 07:44:29 +0000</pubDate>
      <link>https://dev.to/grenguar/aws-certification-exam-preparation-an-ultimate-guide-dbj</link>
      <guid>https://dev.to/grenguar/aws-certification-exam-preparation-an-ultimate-guide-dbj</guid>
      <description>&lt;p&gt;As the demand for cloud computing continues to grow, Amazon Web Services has become one of the industry's most popular cloud service providers. Consequently, AWS certifications are highly sought-after by professionals and teams looking to validate their skills and knowledge in cloud computing.&lt;/p&gt;

&lt;p&gt;However, passing these exams can be challenging, especially for those new to the cloud. Here are some tips and strategies to help you prepare for and confidently pass the AWS certification exams based on my experience passing seven exams. If you're looking to boost your career in cloud computing or expand your knowledge in this field, keep reading to learn more!&lt;/p&gt;

&lt;h2&gt;
  
  
  Find the Motivation
&lt;/h2&gt;

&lt;p&gt;Experience with the public cloud or strong motivation to learn about it should always be the starting point for your exam preparation journey. With proper reason, it will be easier to achieve the result. Are you working on developing a specific skill set to add to the ongoing project or hope to build your credibility for future roles? Find what works best for you, even if it is pretty abstract. And commit to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Select the Right Exam for You
&lt;/h2&gt;

&lt;p&gt;This step is crucial, especially if it is your first certification. By choosing a level that is too challenging for you, you risk burning out and abandoning the idea of getting certified altogether. There are four basic types of exams: foundational, associate, professional, and specialty.&lt;/p&gt;

&lt;p&gt;I usually start by mapping out what I want to achieve with this exam and which skills I want to validate. In doing so, researching the key areas and structure of the exam proves helpful. An excellent place to start is the official &lt;a href="https://aws.amazon.com/certification/"&gt;AWS Certification&lt;/a&gt; page.&lt;/p&gt;

&lt;p&gt;Now let's talk about levels. The only foundational exam is Cloud Practitioner, which is for a reason.&lt;br&gt;
It validates a high-level understanding of AWS cloud services. However, many people I know are jumping straight into the first associate exam.&lt;/p&gt;

&lt;p&gt;It makes life more challenging. The certification journey should start from the beginning, like learning the alphabet before speaking the language.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gcp4w1un--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0txsd40jdgnh1jlcpkdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gcp4w1un--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0txsd40jdgnh1jlcpkdk.png" alt="Cloud Practitioner Badge" width="600" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CP exam makes it easy to understand 'cloud' language. The introductory terms like scaling, load balancing, and foundational services like EC2, Lambda, RDS, DynamoDB, and S3 will be familiar to you. Also, the most significant advantage of going and passing the Cloud Practitioner exam is that you become familiar with the exam process, software, and style of questions.&lt;/p&gt;

&lt;p&gt;If you are still determining which associate level exam to take, Developer or Architect, these levels are quite similar.&lt;br&gt;
If you are choosing between the first associate level exam, choose Architect. The difference in content between it and the Developer one is considerably low.&lt;br&gt;
The ways of preparation would be almost the same. Read more about it later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps: Preparation Begins
&lt;/h2&gt;

&lt;p&gt;Go through the exam guide carefully. Try to answer these questions and put answers into your 'Notes':&lt;br&gt;
What is the exam structure? (questions, duration, etc.)&lt;br&gt;
Which domains are essential, and what is their percentage in the overall score?&lt;/p&gt;

&lt;p&gt;For example: AWS Certified Solutions Architect - Associate.&lt;br&gt;
Let's go to this &lt;a href="https://aws.amazon.com/certification/certified-solutions-architect-associate/?ch=tile&amp;amp;tile=getstarted"&gt;link&lt;/a&gt;. There, you will find the way to download an exam guide. It is heavily focused on the domain of designing secure architectures. It takes 30% of the whole exam. Approximately 20 out of 60 questions will be on this topic. It will help us later in the preparation.&lt;br&gt;
Take note of the table in the 'Content Outline' section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z82l0Kzk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8u0izuckffxoslysww9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z82l0Kzk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u8u0izuckffxoslysww9.png" alt="Content Outline" width="880" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Usually, I spend 1-2 hours studying the course outline and practicalities. Downloading the whitepapers listed as recommended for the exam is also helpful. I recommend also booking the time for the exam well in advance to help you mentally prepare.&lt;/p&gt;

&lt;p&gt;Depending on your workload and the point in the cloud journey, it will take around 2-3 months, with studying 6-7 hours a week except for the foundation exam. Last but not least, notify your partner and family that you are taking the professional challenge of getting well-recognized achievements in your sphere.&lt;/p&gt;

&lt;p&gt;It will help you to receive their support and also manage expectations. For example, it will be a bad idea to plan a vacation four days before the exam unless, of course, you are a superhuman who can study anywhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Preparation
&lt;/h2&gt;

&lt;p&gt;The core of the preparation should be a comprehensive course on one of the learning platforms.&lt;br&gt;
There are many to choose from. As I have asked in my LinkedIn, learners tend to favor ACloudGuru. Also, many say that Adrian Cantrill's courses make outstanding courses. I also heard about Stephane Maarek, who is teaching on Udemy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ui_xRXBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3we73jzgey4p22u83o5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ui_xRXBM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3we73jzgey4p22u83o5d.png" alt="Poll" width="880" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From my experience, starting with any of the courses is essential. Styles are different. In most cases, you must balance theory and practice in the study process. If you are taking your first exam, I recommend reading FAQs about services as additional reading. There are multiple services that you meet most in the exams: EC2, RDS, S3, IAM, SQS, SNS, API Gateway, CloudFront, Lambda, and Route 53.&lt;/p&gt;

&lt;p&gt;Also, in the evening, it is helpful to have a routine of reading a whitepaper from your e-book or tablet for about 30 minutes. I also like to study in the mornings before the chaos of emails, PRs, and business meetings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preliminary Tests
&lt;/h2&gt;

&lt;p&gt;The core preparation should end with completing the main online course, excluding the final test. Also, finishing some of the whitepapers is worth spending time on because they expand knowledge on various matters. Try to start the testing stage 1-2 weeks before the exam. If you are doing a first associate exam, it will probably take two weeks.&lt;/p&gt;

&lt;p&gt;How could you test yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Final exam in the main course&lt;/li&gt;
&lt;li&gt;AWS Sample questions on the page of the exam&lt;/li&gt;
&lt;li&gt;AWS Skill Builder:

&lt;ul&gt;
&lt;li&gt;Exam Readiness: (&lt;em&gt;name of your exam&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;(&lt;em&gt;name of your exam&lt;/em&gt;) Official Practice Question Set (&lt;em&gt;exam code&lt;/em&gt; - English)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;TutorialsDojo practice exams.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to go into the last one after finishing everything. It will help you most if you have experience with questions and understanding the exam. Try to complete as many questions as possible. I found it helpful on the actual exam. Also, reading the explanations after finishing the practice exams is the key to success here.&lt;/p&gt;

&lt;p&gt;Take notes of the most complicated parts for yourself.&lt;br&gt;
It would be related to the differences between security groups and Network Access Control Lists.&lt;br&gt;
Note the tricky sections for yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare for the Exam Day
&lt;/h2&gt;

&lt;p&gt;Consider finishing all the steps above while having 1-2 days before the actual exam. From now on, your main activity will be to read through all your notes and check TutorialsDojo cheatsheets for the services you have difficulties with.&lt;/p&gt;

&lt;p&gt;Also, put the most effort into the sections with the most significant percentage of the exam and the ones which are the points that are most vulnerable for you after passing practice tests.&lt;/p&gt;

&lt;p&gt;Get good sleep during the last 1-2 days. On exam day, walk for 1 hour around a block or to the nearest park.&lt;br&gt;
It usually clears the mind and gives a natural energy boost to your mind and body.&lt;/p&gt;

&lt;p&gt;Take a snack and water bottle with you. What about making it in the comfort of your sofa with the cat on your lap?&lt;br&gt;
Unfortunately, it isn't effortless, and cleaning and preparing the room according to the standards takes time. Also, it feels creepy when somebody is silently watching you struggling with the cloud questions.&lt;/p&gt;

&lt;p&gt;I took only one exam at home. It was an experience that I would rather skip. Taking Cloud Practitioner home is probably not a bad idea as it is straightforward and takes less time. Going to the test center helps me to be in the mode of testing myself. Also, during the exam, there would be the opportunity to take a break for eating, drinking, and walking. It becomes necessary at the professional and specialty levels as you spend more time pondering the questions.&lt;/p&gt;

&lt;p&gt;During the Exam&lt;br&gt;
Checking your name on the screen is a vital thing to do. Please read the questions carefully, and use the paper they give you in the center. It is not possible with the online proctoring option, by the way. Also, you can ask for a change of paper when you finish. First, strive to complete the questions in which you are sure. Use the 'Flag for review' feature because it allows returning after finishing the first round. My experience showed me that you should only mark answers in the problems where you are 95-100% sure. If not, simply mark them later and move forward. You have time to get back to all questions. But if you spend 15 minutes on one question, you will feel more time pressure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Life After Submitting
&lt;/h2&gt;

&lt;p&gt;Be prepared that, in most cases, the final screen will not show you PASS/FAIL score. Get some rest after the exam. I also prefer a day off when there is an exam. Your brain needs a recharge. In any scenario, you did a fantastic job preparing for the exam and learned a lot! High five!&lt;/p&gt;

&lt;h2&gt;
  
  
  Validity of the Certificates
&lt;/h2&gt;

&lt;p&gt;Every exam result will last three years. Remember that every associate exam prolongs the validity of the foundational one. The same happens with the associate exam when you get the professional-level certificate. For example, if you pass Solutions Architect Professional, you will automatically renew the underneath ones like Solutions Architect Associate and Cloud Practitioner. However, Specialty ones do not work like that.&lt;/p&gt;




&lt;p&gt;All these steps will help you to improve your knowledge and advance your career in the cloud.&lt;br&gt;
Certificates help me understand the logic behind the services and their interaction in my day-to-day practice.&lt;br&gt;
Also, they help to keep in mind the most secure and available solutions for the cloud architecture.&lt;br&gt;
And, of course, they give you the credit you deserve for learning all the cool cloud tech!&lt;/p&gt;

&lt;p&gt;Thanks for reading! Good luck, and feel free to reach me for everything related to AWS, serverless, and cloud training.&lt;/p&gt;

&lt;p&gt;Reach me on &lt;a href="https://www.linkedin.com/in/igor-soroka/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>certificate</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Very Nordic Problem: In search of great skiing track</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 27 Jan 2022 08:41:45 +0000</pubDate>
      <link>https://dev.to/aws-builders/very-nordic-problem-in-search-of-great-skiing-track-34db</link>
      <guid>https://dev.to/aws-builders/very-nordic-problem-in-search-of-great-skiing-track-34db</guid>
      <description>&lt;p&gt;&lt;em&gt;Finland is the happiest country on Earth. It has endless forests and lakes. During wintertime, most of the territory has snow. People are using this combo of cold conditions and excellent services. Cross-country skiing is becoming very popular. However, I noticed that the municipality should prepare the forest tracks properly using heavy machinery.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As a ski track user, I would like to be notified when the tracks are fresh and cleaned. If there were maintenance in the morning, the ice on the trails would be an obstacle for comfortable skating-style skiing. In theory, I would like to avoid it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PZg-iFFI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71ewjzugdhsjv0zlrtfh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PZg-iFFI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71ewjzugdhsjv0zlrtfh.jpg" alt="Map" width="880" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Map of the tracks called &lt;a href="https://ulkoliikunta.fi/en/?status=status_ok"&gt;Outdoor Exercise Map&lt;/a&gt; shows the tracks' state. If I want to get the latest data about maintenance, there is the only way - go to the website and check. My motivation behind making the Ski Track Notifier is to stop doing these repetitive tasks. I decided to solve the issue with my favorite technologies: AWS, CDK, Serverless. All the code examples in this article focus on Typescript. The project code is on &lt;a href="https://github.com/Grenguar/ski-track-condition-notifier"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;The idea behind the application is to use as many managed services as possible. It will mean that the price will be only for the invocations. AWS Lambda is the primary business logic executor. The app calls it periodically to check the Helsinki region Service Map API. &lt;/p&gt;

&lt;p&gt;The flow is going as follows. The EventBridge rule calls AWS Lambda every 30 minutes. The function checks the API and filters out the ski tracks which were not ready inside the time interval of 60 minutes. There is an SNS topic to gather the PublishCommands from Lambda. It has an e-mail subscription as a notification target. Here is the architecture of the solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HDgWT3A8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rpqhf9qpvwmby5na7k5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HDgWT3A8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8rpqhf9qpvwmby5na7k5.png" alt="architecture diagram" width="880" height="350"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tooling
&lt;/h2&gt;

&lt;p&gt;I decided to make development and deployment as easy as possible. It is a small project which should be free for hosting and fast to put into production. This section will speak about the technologies used for the application. I would start from the cloud resources to the actual business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Resources
&lt;/h3&gt;

&lt;p&gt;Infrastructure as Code and CI/CD pipeline allow me to make my application available in minutes from the 'master' branch. I used CDK with CDK Pipelines for provisioning resources. I talked about the CI/CD process more in this &lt;a href="https://dev.to/aws-builders/how-to-automate-the-deployment-with-cdk-pipelines-2fn5"&gt;article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Because I am working alone on this project, there is no need for a multi-branch setup. There are two CloudFormation stacks in the project. One is responsible for CI/CD pipeline made with the CodePipeline service. Another stack is for implementation. It consists of Lambda, SNS, permissions, and EventBridge Trigger Rule in a nutshell. &lt;/p&gt;



&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;

&lt;p&gt;I used the monorepo approach, where the implementation and the infrastructure instructions live in the same codebase. Beforehand there were two issues with this approach:&lt;br&gt;
Two 'package.json' files in the source folder and the 'infra' one for dependencies created a dependency mess. It means that there will be two package-lock and two folders with node_modules.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NBlouGs7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zuvt2lesehf03dawxrt.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NBlouGs7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0zuvt2lesehf03dawxrt.jpg" alt="Folder structure" width="366" height="319"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Packaging lambda code dependencies meant having an extra step of the building and packing it. One could do it via lambda layer or external bundler like &lt;code&gt;webpack&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Thanks to CDK team, now there is a construct called &lt;code&gt;NodejsFunction&lt;/code&gt;. It solves precisely these problems by simplifying the build process and code structure. According to the creators, it uses an &lt;code&gt;esbuild&lt;/code&gt; that should be 'extremely fast'. I tried it, and it blew my mind with simplicity. My function resource looks like this with just an entry point to generate a valid bundled js file with the tree-shaking. This approach will pack exactly this function without having a whole folder in the cloud.&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;getSkiTrackStateHandler&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;aws_lambda_nodejs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;join&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../src/functions/get-ski-track-state.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One will run only four commands to complete building a valid CloudFormation template. The instructions generated from this array:&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;buildCommands&lt;/span&gt; &lt;span class="o"&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;npm i&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;npm run build&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;npm run test&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;npx cdk synth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Business Logic
&lt;/h3&gt;

&lt;p&gt;I mainly used the TDD (Test-Driven Development) approach to develop the implementation. My idea was to decouple the API call made with Axios GET request from the actual filtering. Keeping this in mind helps to test it faster. I could create a fixture with the sample ski tracks. For the tests, I used jest.&lt;/p&gt;

&lt;p&gt;The API returns a JSON object. Every ski track has a key called &lt;code&gt;observations&lt;/code&gt;. It is an array of objects that should have &lt;code&gt;property&lt;/code&gt; each.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;observations:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;unit:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;54322&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;545294&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;property:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'ski_trail_condition'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;time:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;2022-01-07&lt;/span&gt;&lt;span class="err"&gt;T&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;48.129560&lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0200&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;expiration_time:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;name:&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;fi:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Hyvä'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;sv:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Bra'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;en:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Good&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;condition'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;quality:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'good'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;value:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'good'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;primary:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;unit:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;54322&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;id:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;545293&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;property:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'ski_trail_maintenance'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;time:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="mi"&gt;2022-01-07&lt;/span&gt;&lt;span class="err"&gt;T&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;48.129560&lt;/span&gt;&lt;span class="err"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0200&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;expiration_time:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;name:&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;fi:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Kunnostettu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;sv:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Iståndsatt'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="err"&gt;en:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Maintenance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;finished'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;quality:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'unknown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;value:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'maintenance_finished'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="err"&gt;primary:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I need to have &lt;code&gt;ski_trail_condition&lt;/code&gt; with the &lt;code&gt;good&lt;/code&gt; value. Also, there is &lt;code&gt;ski_trail_maintenance&lt;/code&gt;. It should have value with the &lt;code&gt;maintenance_finished&lt;/code&gt;. One more condition is to have it in the last hour. For the time comparisons, there is a library called &lt;code&gt;luxon&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example
&lt;/h2&gt;

&lt;p&gt;Here is the screenshot of the letter sent to the e-mail. It has the track's name, parsed date, and address. Surprisingly, maintenance data comes with the delay to the API. That is why it is essential to have this ratio between running each lambda and checks of the track update age. After couple of experiments it was like 30/60 minutes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ocjELgCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylyji1a3abpl94d5q79b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ocjELgCI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylyji1a3abpl94d5q79b.jpg" alt="Letter example" width="880" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Future work
&lt;/h2&gt;

&lt;p&gt;Of course, there are more insights about the tracks in the API. For example, 'valaistu' means the availability of artificial light on the tracks. Also, there is a distance shown in kilometers.&lt;/p&gt;

&lt;p&gt;Now the application supports only one subscriber. In the future, it would be great to have multiple subscribers, the ability to choose municipality, and track choice of the main focus. Also, it would be nice to connect something like an Amazon Lex-powered bot for multiple channels.&lt;/p&gt;

&lt;p&gt;One other idea is to send notifications in batches. The current implementation has the drawback of sending multiple e-mails if there are recent maintained tracks. Today, there is no separate check that the notification about a particular object has been sent to the subscriber.&lt;/p&gt;




&lt;p&gt;It took a couple of evenings to create a small full-fetched application to notify myself about the changes found in the public API. With the power of serverless and event-driven architecture, one could deliver business value fast without worrying about servers, virtual machines, or containers. Thanks for reading! Follow me on twitter: &lt;br&gt;
&lt;/p&gt;
&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--2v9HFv-U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1453302847592976384/girU0zFG_normal.jpg" alt="Igor Soroka profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Igor Soroka
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/grenguar"&gt;@grenguar&lt;/a&gt;
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      After watching cloud educational content on 2x speed, I noticed that every instructor sounds sad at normal playback.
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      10:21 AM - 17 Jan 2022
    &lt;/div&gt;


    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1483021717874388994" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1483021717874388994" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1483021717874388994" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


</description>
      <category>aws</category>
      <category>devops</category>
      <category>typescript</category>
      <category>serverless</category>
    </item>
    <item>
      <title>How could you be certified with AWS DevOps Professional? </title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 20 Jan 2022 10:27:23 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-could-you-be-certified-with-aws-devops-professional-1eah</link>
      <guid>https://dev.to/aws-builders/how-could-you-be-certified-with-aws-devops-professional-1eah</guid>
      <description>&lt;p&gt;Last year, I felt that it was time to have more certifications. I have a Developer Associate certificate, so getting a Solutions Architect Associate one should not be an issue. I was wrong. It took time to get into the flow of the studying. Passing exams is a skill you should develop through an effective routine and development mindset. &lt;/p&gt;

&lt;p&gt;Recently I went to certification on DevOps professional. My background is in Development mostly. However, I spent my time setting up environments and infrastructure during recent years. It is worth mentioning that my typical stack includes AWS Lambda, DynamoDB, S3, API Gateway, and SNS/SQS. Here is my list of tips and materials for passing your DevOps professional certificate. You could combine them in any order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;General recommendations&lt;/strong&gt;. Do not underestimate the content, syllabus, and time during the exam preparation. Sitting on the exam for 3 hours could be challenging. I took the exam in the Pearson VUE accredited test center. I got two A4 papers for writing. With the online option, you will not have a chance to write anything. The notes during the exam helped to map the question and refresh it during the review part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pass SysOps Administrator
&lt;/h2&gt;

&lt;p&gt;Try to focus on on monitoring, deployments. This exam will benefit the parts regarding deployments, auditing, and monitoring. Take 1-2 months for the DevOps preparation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read whitepapers
&lt;/h2&gt;

&lt;p&gt;I was skipping them during associate ones. They build the correct mindset towards implementation on how to follow AWS practices. I advise you to read them before sleep. Here is the official list&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%2Fkpg2c7qagif4qg4z1b9d.jpg" 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%2Fkpg2c7qagif4qg4z1b9d.jpg" alt="whitepapers list"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Main Course
&lt;/h2&gt;

&lt;p&gt;Complete one course with Labs. Any platform will work. There are plenty of them, but the most accessible ones are ACloudGuru or CloudAcademy. Making quick hand-written notes is helpful on the last days before the exam.&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%2Fssyrap8ihgt910mdb7wx.jpg" 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%2Fssyrap8ihgt910mdb7wx.jpg" alt="exam note example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Skill Builder
&lt;/h2&gt;

&lt;p&gt;It is a new official online learning platform from the AWS itself. The quality of the content is outstanding. One drawback is that you need to register but it is for free. &lt;/p&gt;

&lt;p&gt;I recommend these courses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Getting Started with DevOps on AWS&lt;/li&gt;
&lt;li&gt;AWS Certification Official Practice Question Sets (sample test is free now for any of the exams)&lt;/li&gt;
&lt;li&gt;Exam Readiness: AWS Certified DevOps Engineer - Professional&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Train yourself
&lt;/h2&gt;

&lt;p&gt;Sit the actual 75 questions in one go (TutorialsDojo practice exams or the one at the end of the course). Do not be demotivated by the results of the practice exams. &lt;/p&gt;

&lt;p&gt;Topics and services to concentrate on: Beanstalk, Config, Trusted Advisor, Auto Scaling, CloudFront, CodeDeploy, Systems Manager, S3, Logging, CloudTrail, CodeCommit.&lt;/p&gt;

&lt;p&gt;If you have a couple of days before an exam - concentrate on the most complicated areas. Read tutorialsdojo's cheatsheets. They are enormously helpful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Config (&lt;a href="https://tutorialsdojo.com/aws-config/" rel="noopener noreferrer"&gt;cheatsheet&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;CodeDeploy (&lt;a href="https://tutorialsdojo.com/aws-codedeploy/" rel="noopener noreferrer"&gt;cheatsheet&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Deployment tools comparison (&lt;a href="https://tutorialsdojo.com/elastic-beanstalk-vs-cloudformation-vs-opsworks-vs-codedeploy/" rel="noopener noreferrer"&gt;cheatsheet&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Installation of CodeDeploy Agent (&lt;a href="https://www.youtube.com/watch?v=P4K3HB8TNJo" rel="noopener noreferrer"&gt;video&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Systems Manager (&lt;a href="https://tutorialsdojo.com/aws-systems-manager/" rel="noopener noreferrer"&gt;cheatsheet&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Physical aspect
&lt;/h2&gt;

&lt;p&gt;Sleep well, do physical exercises, spend time outdoors. Take a break during the exam for standing and stretching. Avoid consuming too much caffeine and sugar especially in the last week before the exam. In the end, all of these factors accumulates into tiredness and lack of concentration. For improving focus, it is nice to do meditation or yoga.&lt;/p&gt;

&lt;p&gt;The exam is challenging, but you could become an AWS-certified professional with extensive preparation and discipline. If you could learn at least one lesson from this article, it would mean for me that it was worth sharing. Thanks for reading! Follow me on Twitter also:&lt;br&gt;&lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1483021717874388994-863" src="https://platform.twitter.com/embed/Tweet.html?id=1483021717874388994"&gt;
&lt;/iframe&gt;

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



&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>tutorial</category>
      <category>career</category>
    </item>
    <item>
      <title>Story about my cloud journey and becoming an AWS Community Builder
</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 11 Nov 2021 15:11:07 +0000</pubDate>
      <link>https://dev.to/aws-builders/story-about-my-cloud-journey-and-becoming-an-aws-community-builder-e53</link>
      <guid>https://dev.to/aws-builders/story-about-my-cloud-journey-and-becoming-an-aws-community-builder-e53</guid>
      <description>&lt;p&gt;More than a month passed after the news that I became an AWS Community Builder in Serverless Category. Today I would like to tell a story about my path to the cloud. I would also reflect on why it is essential to be a part of this community. &lt;/p&gt;

&lt;h3&gt;
  
  
  Public Cloud Start
&lt;/h3&gt;

&lt;p&gt;My path to the cloud started with a stupid idea. It was to make a telegram bot that could show the menus of the restaurants on the university campus. There were approximately five places to eat with a very varied quality of food. Some days the choice was obvious - visit Restaurant X. Other days it was challenging to decide. My bot would have the ability to get the menu in the palm of my hand without going and checking the website.&lt;/p&gt;

&lt;p&gt;The language was NodeJS, and the cloud provider was Heroku. It was my first trial to do something with server-side javascript. At the same time, I learned about this great tool called Cloud9. Now it is a part of AWS. Those times I was impressed that I could run my bot from any computer (my laptop or the school one). Also, I could prototype fast and check the solution in the Telegram messenger. &lt;/p&gt;

&lt;h3&gt;
  
  
  JS Conference and first Lambda
&lt;/h3&gt;

&lt;p&gt;After my playground with the chatbot, I got a real programming job. The technology stack consisted of a Java monolith with an on-premise server. I took a challenge because my primary language was Java those times. However, secretly I was excited about NodeJS world with a lot of exciting things happening around it.&lt;/p&gt;

&lt;p&gt;That is why I decided to visit a conference about JavaScript called HolyJS in Saint-Petersburg. There I chose almost randomly the session about AWS Lambda conducted by Slobodan Stojanović. It was a revelation. At this time, I have spent half a year deploying Java modules to a running app from the CLI. &lt;/p&gt;

&lt;p&gt;How can it be possible? No patching, no infrastructure to manage. It blew my mind. I returned to Finland and started creating my first API with API Gateway backed by Lambdas. I made my first AWS account which was incredible and strange. There was an endless amount of unfamiliar services.&lt;/p&gt;

&lt;h3&gt;
  
  
  Corporate world and certificate
&lt;/h3&gt;

&lt;p&gt;It has taken a while after I took a new position in an IT consulting company. Again it was a Java monolith but deployed to AWS with automatic deployments. I learned a lot about working in different locations with distributed teams.&lt;/p&gt;

&lt;p&gt;There was a company-wide program for being certified with AWS. It was amazing that now I could have time to know all these tiles in the console. I started to study and experiment with various services. Then I was certified as a Developer Associate. It gave me confidence that now I could use AWS in all of my projects.&lt;/p&gt;

&lt;p&gt;The next project in a corporation gave me a chance to deploy my lambdas to production. There I learned more about Terraform, CloudFormation, and Serverless framework. It felt so cool to write the infrastructure which could be re-created by one-line command. I learned more about CI/CD. Like in many cases, nobody wanted to set up deployments and connect all parts. &lt;/p&gt;

&lt;p&gt;We deployed the ECS cluster with Docker containers. I learned that serverless is not only Lambdas. It is more like philosophy where one is not provisioning virtual machines but focusing on the application code and business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freelancing and community
&lt;/h3&gt;

&lt;p&gt;I took a chance to jump into individual contracting in the middle of 2020 after an unexpected call from a recruiter.  It was a 100% serverless project with a geographically distributed team. I learned so much from the people with whom I worked. It happened to be the exact match for the technology stack. We used SQS/SNS, S3, Lambdas, Kinesis, and CloudFormation/SAM. It became a standard for me to find such teams and work with them. I learned a lot about provisioning infrastructure with code.&lt;/p&gt;

&lt;p&gt;In 2021 I spent time setting up cloud-native projects mainly using CDK. The stack that drives me is still serverless, but now I can write application code and infrastructure one with the same language, Typescript. I have started to write about this more and more. Blogging allows me to stop and reflect on the topics that re-ignite my passion for building new things.&lt;/p&gt;

&lt;p&gt;In August, I applied to the AWS Community Builders program because I started to feel the idea of unity that technology gives us. Sharing knowledge and meeting new people online became important. In my application, I said honestly that this would motivate me to write more about my path in the cloud.&lt;/p&gt;

&lt;p&gt;In October, the letter said that people from AWS accepted me. I got an invitation to the community in Slack. After the first days, I was astonished by the idea that there are program participants from worldwide. It was a revelation for me. People are writing blogs, shooting videos, sharing knowledge. I am learning every day about new features and things people experiment with at their time. Also, I resumed my path with achieving AWS certificates partly because of how many people are doing them inside the community.&lt;/p&gt;

&lt;p&gt;My journey in the cloud is continuing. I am working with AWS every day as a consultant and engineer. Also, now I am speaking more often about my infrastructure-as-code findings with CDK and serverless. Thanks for reading this article. You can find me on &lt;a href="https://twitter.com/Grenguar"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/igor-soroka/"&gt;LinkedIn&lt;/a&gt;. Do not hesitate to write and ask questions about AWS, Serverless, and IaC. I will be happy to answer them.&lt;/p&gt;


&lt;blockquote class="ltag__twitter-tweet"&gt;

  &lt;div class="ltag__twitter-tweet__main"&gt;
    &lt;div class="ltag__twitter-tweet__header"&gt;
      &lt;img class="ltag__twitter-tweet__profile-image" src="https://res.cloudinary.com/practicaldev/image/fetch/s--2v9HFv-U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://pbs.twimg.com/profile_images/1453302847592976384/girU0zFG_normal.jpg" alt="Igor Soroka profile image"&gt;
      &lt;div class="ltag__twitter-tweet__full-name"&gt;
        Igor Soroka
      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__username"&gt;
        &lt;a class="mentioned-user" href="https://dev.to/grenguar"&gt;@grenguar&lt;/a&gt;

      &lt;/div&gt;
      &lt;div class="ltag__twitter-tweet__twitter-logo"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ir1kO05j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-f95605061196010f91e64806688390eb1a4dbc9e913682e043eb8b1e06ca484f.svg" alt="twitter logo"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__body"&gt;
      Excited to speak about CDK magic for serverless! &lt;a href="https://t.co/S7BbhjnrqE"&gt;twitter.com/jawsdays/statu…&lt;/a&gt;
    &lt;/div&gt;
    &lt;div class="ltag__twitter-tweet__date"&gt;
      13:51 PM - 09 Nov 2021
    &lt;/div&gt;

      &lt;div class="ltag__twitter-tweet__quote"&gt;
        &lt;div class="ltag__twitter-tweet__quote__header"&gt;
          &lt;span class="ltag__twitter-tweet__quote__header__name"&gt;
            JAWS-UG
          &lt;/span&gt;
          @jawsdays
        &lt;/div&gt;
        #jawspankration セッション紹介/Session Introduction🤼‍♂️

&lt;a class="mentioned-user" href="https://dev.to/grenguar"&gt;@grenguar&lt;/a&gt;


https://t.co/xeqfpQgXZL

🥊イベント参加申込はこちら/Click here to register for the event.
https://t.co/usvK3fZYAD
#aws #jawsug #jawspankration2021 https://t.co/uRAeeXsXOl
      &lt;/div&gt;

    &lt;div class="ltag__twitter-tweet__actions"&gt;
      &lt;a href="https://twitter.com/intent/tweet?in_reply_to=1458069685967233024" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fFnoeFxk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-reply-action-238fe0a37991706a6880ed13941c3efd6b371e4aefe288fe8e0db85250708bc4.svg" alt="Twitter reply action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/retweet?tweet_id=1458069685967233024" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k6dcrOn8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-retweet-action-632c83532a4e7de573c5c08dbb090ee18b348b13e2793175fea914827bc42046.svg" alt="Twitter retweet action"&gt;
      &lt;/a&gt;
      &lt;a href="https://twitter.com/intent/like?tweet_id=1458069685967233024" class="ltag__twitter-tweet__actions__button"&gt;
        &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SRQc9lOp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/twitter-like-action-1ea89f4b87c7d37465b0eb78d51fcb7fe6c03a089805d7ea014ba71365be5171.svg" alt="Twitter like action"&gt;
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/blockquote&gt;


</description>
      <category>aws</category>
      <category>programming</category>
      <category>career</category>
    </item>
    <item>
      <title>Migration to CDK with existing infrastructure</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 04 Nov 2021 08:27:02 +0000</pubDate>
      <link>https://dev.to/aws-builders/migration-to-cdk-with-existing-infrastructure-4ij6</link>
      <guid>https://dev.to/aws-builders/migration-to-cdk-with-existing-infrastructure-4ij6</guid>
      <description>&lt;p&gt;Yesterday (November 3, 2021), I presented on the November meetup of ServerlessDays Amsterdam, where I introduced using CDK with serverless use-cases. After that, I thought about migrating to CDK for the teams that have already chosen this fantastic deployment framework. &lt;/p&gt;

&lt;p&gt;Here is the link for the recording. &lt;/p&gt;

&lt;p&gt;Time codes: &lt;strong&gt;3:20 - 23:30&lt;/strong&gt;&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/3VxOFDQW5yI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Examples from the presentation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Grenguar/cdk-billing-alert" rel="noopener noreferrer"&gt;Billing Alert&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Grenguar/aws-cdk-api-workshop" rel="noopener noreferrer"&gt;Serverless API with CI/CD Pipeline&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  You sold me CDK! What's next?
&lt;/h2&gt;

&lt;p&gt;Let's imagine the debate over using Infrastructure as a Code tool is over. One could go and start with Cloud Formation Kit. There are other options, of course. I spoke of them in my other article. What steps could one take for migrations? &lt;/p&gt;

&lt;h3&gt;
  
  
  Greenfield project
&lt;/h3&gt;

&lt;p&gt;We are developing a developer's dream project with the latest and freshest tools. With this in mind, let's create new infrastructure stacks. The most important is to go straight to CDK. The one issue will be choosing the language. Here it depends on the primary language of the team. The front-end teams would prefer Typescript. Java backend people will use this language. &lt;/p&gt;

&lt;h3&gt;
  
  
  From No-Infrastructure-as-Code
&lt;/h3&gt;

&lt;p&gt;This case can be a challenge. Here try to group resources in stacks and find a way to connect them. If you have more than 20 resources, it could be better to create a separate stack. Also, using constructs could help for logical grouping. Think of them as modules. &lt;/p&gt;

&lt;h3&gt;
  
  
  From Cloudformation/other tools
&lt;/h3&gt;

&lt;p&gt;One could use the hybrid approach where the template will be together in the same project with the CDK application. An example could be a pipeline provisioned with CloudFormation. The infra for business logic would use a programming language.&lt;/p&gt;

&lt;p&gt;A similar approach could work with other deployment tools. There are multiple ways to connect stacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By outputs &lt;/li&gt;
&lt;li&gt;By creating shared SSM Parameter Store/Secrets Manager&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The latter one gives the ability to create a resource, save its id in one stack. One could use it in a different stack as a parameter. However, both approaches could work depending on the needs. Usage of outputs is widespread because one does not care which tool was used. However, secrets give a way to use any resource from any stack that other teams created.&lt;/p&gt;

&lt;p&gt;Thanks for reading and watching me! Follow me on Twitter: &lt;br&gt;
&lt;iframe class="tweet-embed" id="tweet-1447457840562593796-864" src="https://platform.twitter.com/embed/Tweet.html?id=1447457840562593796"&gt;
&lt;/iframe&gt;

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



&lt;/p&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>devops</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Checklist for securing the usage of AWS account from unexpected events</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 28 Oct 2021 05:45:38 +0000</pubDate>
      <link>https://dev.to/aws-builders/checklist-for-securing-the-usage-of-aws-account-from-unexpected-events-48e</link>
      <guid>https://dev.to/aws-builders/checklist-for-securing-the-usage-of-aws-account-from-unexpected-events-48e</guid>
      <description>&lt;p&gt;Last month I got the bill of 60 USD dollars for the usage of the AWS account. It was too much for my small experiments and blogs articles. That is why I decided to write this checklist about securing your account and making the expenses manageable for your account. As a bonus, I made a CDK project for deploying the billing alarm in the last chapter of this article.&lt;/p&gt;

&lt;p&gt;The steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add MFA&lt;/li&gt;
&lt;li&gt;Create admin user&lt;/li&gt;
&lt;li&gt;Renew CLI access credentials &lt;/li&gt;
&lt;li&gt;Double-check all regions for resources&lt;/li&gt;
&lt;li&gt;Setup billing alert (cdk project in this guide)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Add MFA on root user
&lt;/h3&gt;

&lt;p&gt;Passwords are already not helping with account protection. So, having one more authentication method will prevent it from being hacked. My preferred way is to use 1Password. It has built-in support for one-time codes. I found it handy when once a phone has stayed at home during my day in coworking. The 1Password application was running on my laptop with the MFA connected to the AWS account. It saved my day. &lt;/p&gt;

&lt;h3&gt;
  
  
  Separate user with AdministratorAccess
&lt;/h3&gt;

&lt;p&gt;There is a temptation to skip tedious user setup on a freshly created AWS account. The one wants to start using the cloud as fast as possible. I was in that situation. However, it is considered a bad practice to manage the resources from the root user. &lt;/p&gt;

&lt;p&gt;If a hacker gets account access, it will be a real issue. Somebody will have the ability to mine cryptocurrency with the EC2 instances. So, to avoid this issue - create a separate user with Console and programmatic access who has the AdministratorAccess role. Do not forget to add MFA to this account also.&lt;/p&gt;

&lt;h3&gt;
  
  
  Re-new programmatic access
&lt;/h3&gt;

&lt;p&gt;I had credentials for CLI access created more than 365 days ago. It is a security risk also. The main idea here is to refresh them not tomorrow but today. Also, do not expose access key ID and secret access key, especially when committing to GitHub. &lt;/p&gt;

&lt;h3&gt;
  
  
  Double-check all regions for resources
&lt;/h3&gt;

&lt;p&gt;There can be a situation when some costs are always in the bill. It means that something is still eating the budget. The most dangerous AWS services in terms of costs are VPC, ECS, and EC2. These have a pay-as-you-go model. &lt;/p&gt;

&lt;p&gt;It means that every instance of EC2 has billing in seconds. Another trick is that the ECS cluster with Fargate services running will have costs.  For example, it is a Java Spring app with logging every second. Fargate is a serverless way of running containers, which does not have a hefty invoice at the end of the month. Logging will require spinning up the service over and over again to infinity. That is what happened to me when I got the bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup a billing alert
&lt;/h3&gt;

&lt;p&gt;Billing issues are the motivation for this article, as one could guess. That is why I am suggesting setting up a billing alarm. It will send the notification to the email when the threshold crosses the desired amount in USD. For my case, I took 5 dollars. &lt;/p&gt;

&lt;p&gt;I have created a small CDK project for that. One could find it on GitHub &lt;a href="https://github.com/grenguar/cdk-billing-alert" rel="noopener noreferrer"&gt;here&lt;/a&gt;. What are we doing here? The billing alarm will have a metric for the &lt;code&gt;EstimatedCharges&lt;/code&gt;. It will notify SNS topic with an email subscription. The best part of this is that the project is entirely serverless. It will cost you nothing for the timebeing.&lt;/p&gt;

&lt;p&gt;There are several steps to achieve a calm mind regarding your expenses in the cloud:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set email with SSM, like:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm put-parameter &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/billing/email"&lt;/span&gt; &lt;span class="nt"&gt;--type&lt;/span&gt; &lt;span class="s2"&gt;"String"&lt;/span&gt; &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your email&amp;gt;"&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; &amp;lt;&lt;span class="k"&gt;if &lt;/span&gt;you are using it&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Clone the repo and install dependencies (in Linux/macOS case)
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Grenguar/cdk-billing-alert.git
&lt;span class="nb"&gt;cd &lt;/span&gt;cdk-billing-alert
&lt;span class="nb"&gt;cd &lt;/span&gt;infra
npm i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;If you want to change the threshold, do it in the &lt;code&gt;infra/bin/infra.ts&lt;/code&gt; file. There is a parameter called &lt;code&gt;monetaryLimit&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Do the deployment:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cdk deploy &lt;span class="nt"&gt;--profile&lt;/span&gt; &amp;lt;&lt;span class="k"&gt;if &lt;/span&gt;you are using it&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the result in the CloudWatch -&amp;gt; Alarms -&amp;gt; All alarms.&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%2F7t4e5beibf05bs4sz2pz.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%2F7t4e5beibf05bs4sz2pz.png" alt="Billing alert demo"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Of course, these actions are not giving 100% protection from hackers or unexpected bills. However, the chance of getting strange news from AWS about your cloud resources decreases with every completed point from this checklist. Do you have any actions of improving the security and stabilizing your bill with AWS? &lt;/p&gt;

</description>
      <category>aws</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to automate the deployment with CDK Pipelines</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 21 Oct 2021 07:01:09 +0000</pubDate>
      <link>https://dev.to/aws-builders/how-to-automate-the-deployment-with-cdk-pipelines-2fn5</link>
      <guid>https://dev.to/aws-builders/how-to-automate-the-deployment-with-cdk-pipelines-2fn5</guid>
      <description>&lt;p&gt;&lt;em&gt;Modern software projects are going to be complicated to develop and maintain without automation. The most sophisticated way will be to create a pipeline for the project for sourcing, building, and deploying new changes. This article continues the previous one that was telling about the deployment of public serverless API. Here we will be doing further automation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What was the project? It gives the ability to store, retrieve, edit and delete books from the Rest API. If you are going to follow instructions, it will be worth having the git repository cloned. It is situated &lt;a href="https://github.com/Grenguar/aws-cdk-api-workshop" rel="noopener noreferrer"&gt;here&lt;/a&gt;. First, it is crucial to have a common vocabulary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Glossary
&lt;/h3&gt;

&lt;p&gt;Used terms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;implementation code - the main application situated in the root folder&lt;/li&gt;
&lt;li&gt;implementation stack - the one which has the infra code for lambdas, API GW and &lt;/li&gt;
&lt;li&gt;pipeline stack - magical one which has the CI/CD logic in it, including self-mutation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Overview of Manual Steps
&lt;/h3&gt;

&lt;p&gt;In a nutshell, there are a couple of manual steps for succeeding. However, in the end, we will create the pipeline that will be getting the changes and check them in the infrastructure and implementation both. Here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating GitHub Connection using AWS Codestar&lt;/li&gt;
&lt;li&gt;Provisioning CDKToolkit (new or updated)&lt;/li&gt;
&lt;li&gt;Provisioning of CodePipeline from CLI &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Connect GitHub as a source
&lt;/h3&gt;

&lt;p&gt;Let's start with the very beginning of the project building process. The pipeline should be able to get the code from the GitHub repository. In old times, one should store the secret of the GitHub webhook. Now there is a second version of it. &lt;/p&gt;

&lt;p&gt;For using that, we will be setting up a connection. It is a region-specific service situated in &lt;a href="https://console.aws.amazon.com/codesuite/settings/connections" rel="noopener noreferrer"&gt;'Developer Tools -&amp;gt; Connections'&lt;/a&gt;. One should click 'Create Connection.' In this step, there are three options: BitBucket, GitHub, AWS Connector for GitHub.&lt;/p&gt;

&lt;p&gt;The connection requires the installation of 'AWS Connector for GitHub.' There are options to choose either all repositories from the account or selected ones.&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%2Fm0m0faw8wzoetttn5h3z.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%2Fm0m0faw8wzoetttn5h3z.png" alt="AWS Connector"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the next screen, there is an ARN of this connection. One should write it down because the first stage of the pipeline will use it. From experience, it is better to save it into SSM Parameter Store situated &lt;a href="https://eu-west-1.console.aws.amazon.com/systems-manager/parameters/" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The path to the secret could be like&lt;br&gt;
&lt;code&gt;/serverless-api/git/connection-arn&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Preparing pipeline stack
&lt;/h3&gt;

&lt;p&gt;The traditional approach of creating the CodePipeline projects is to have every stage described like sourcing, building, and deploying. The main issue was that everything like output artifacts and execution roles would be described from the ground-up.&lt;/p&gt;

&lt;p&gt;However, IaC tools are evolving. CDK has the concept of 'Construct,' which is basically a group of resources. There is a new one called &lt;code&gt;aws-cdk-lib/pipelines.&lt;/code&gt; It solves the above-mentioned problems of provisioning additional resources by hand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;connectionArn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 
  &lt;span class="nx"&gt;ssm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StringParameter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;valueForStringParameter&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;/serverless-api/git/connection-arn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&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;pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CodePipeline&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;Pipeline&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;pipelineName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ServerlessAPI-Pipeline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;synth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ShellStep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Build&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;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CodePipelineSource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Grenguar/aws-cdk-api-workshop&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;main&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;connectionArn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;connectionArn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="p"&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;npm ci&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;npm run build&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;cd infra&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;npm ci&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;npm run build&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;npx cdk synth&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;mv cdk.out ../&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;selfMutation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addStage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MyPipelineAppStage&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;Deploy&lt;/span&gt;&lt;span class="dl"&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 synth option is the first we can start to discuss. It is basically our build stage all-in-one stop. SSM stores the connection ARN. It is a comprehensive security practice for putting it into managed service for secrets. The first argument for input connection is &lt;code&gt;&amp;lt;owner&amp;gt;/&amp;lt;repository_name&amp;gt;&lt;/code&gt;. This will work with the corporate accounts also. &lt;/p&gt;

&lt;p&gt;The commands option is basically a replacement for the buildspec. It is a sequence of commands which will be executed by the builder. In CDK, it is implemented as an array of strings. It can be handy for parametrization. It is important to note that first, the webpack project should be dealt with. Only after that will there be &lt;code&gt;code&lt;/code&gt; folder with our lambdas. Without that, infrastructure will fail.&lt;/p&gt;

&lt;p&gt;Self mutation gives the ability for the pipeline to be changed by itself. Previously, it was painful to change the settings of it. Now there are two stacks: implementation and pipeline. Both of them would be checked and deployed. 'MyPipelineAppStage' is the stack that has API Gateway, Lambdas, and DynamoDB table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choosing the main stack
&lt;/h2&gt;

&lt;p&gt;Previously there was only one CloudFormation stack - ApiStack. Now our primary stack is becoming the Pipeline one. In this case, the implementation stack becomes a Stage. It is a unit that has one or more stacks that would be deployed together. In this case, &lt;code&gt;infra/bin/infra.ts&lt;/code&gt; is the application entry. It will have only one stack to provision the pipeline (PipelineStack), whereas implementation one will be packed as a stage for ShellStep. The code example is here.&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;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyPipelineAppStage&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Stage&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&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;StageProps&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApiStack&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;APIStack&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Provisioning CDK Tools
&lt;/h3&gt;

&lt;p&gt;If one wants to use cdk, it is necessary to provision CDKToolkit. There is a one-line command for that. However, there are multiple versions of these tools. When I was preparing this article, my case was a problematic one. Deployments were not successful because of not enough rights for the CloudFormation to provision resources. For that case, I created &lt;strong&gt;Troubleshooting&lt;/strong&gt; part of this article. Refer to it before having issues with deployments. For the first-timers:&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;export &lt;/span&gt;&lt;span class="nv"&gt;CDK_NEW_BOOTSTRAP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1
npx cdk bootstrap aws://&lt;span class="nv"&gt;$ACCOUNT&lt;/span&gt;/REGION
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why are we using &lt;code&gt;npx&lt;/code&gt;? In short: it will run cdk without the need to have it globally. From npx docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Executes &amp;lt;command&amp;gt; either from a local node_modules/.bin, 
or from a central cache, installing any packages 
needed in order for &amp;lt;command&amp;gt; to run.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Time to build and deploy
&lt;/h3&gt;

&lt;p&gt;We are almost done. Now the only thing is to run the command to provision pipeline from the &lt;code&gt;infra&lt;/code&gt; folder. It would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! Now we can relax and wait for a couple of minutes for the pipeline to succeed. The image shows the pipeline generated after that. &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%2Frjh7s6agvwp9v4893ey5.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%2Frjh7s6agvwp9v4893ey5.png" alt="AWS CodePipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is sourcing the code from the latest git commit. After that, it builds the code according to the instructions in ShellStep. The third stage is checking the changes in the pipeline itself. The next one is interesting because it has two groups of artifacts. One is for the implementation code of lambdas. Another one is a handler for the custom Lambda resource for creating log groups and retention policies. The deployment stage will check the changeset of the generated CloudFormation project. &lt;/p&gt;




&lt;p&gt;In this article, I presented the modern way of creating CI/CD pipelines. The serverless use case is the most natural for me. However, one can use these findings for provisioning EC2 instances or ECS clusters. &lt;/p&gt;

&lt;h3&gt;
  
  
  Troubleshooting
&lt;/h3&gt;

&lt;p&gt;If the stack on the deployment stage is failing. Probably, you have issues with the 'CDKToolkit'. You will need to do these actions.&lt;/p&gt;

&lt;p&gt;So, what I did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Found ‘CDKToolkit’ in CFN. There I noted the S3 bucket.&lt;/li&gt;
&lt;li&gt;Deleted the toolkit stack.&lt;/li&gt;
&lt;li&gt;Deleted the bucket&lt;/li&gt;
&lt;li&gt;Did exactly like it was said in tutorial:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cdk bootstrap aws://&amp;lt;account&amp;gt;/eu-west-1 &lt;span class="nt"&gt;--profile&lt;/span&gt; &amp;lt;profile&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--cloudformation-execution-policies&lt;/span&gt; arn:aws:iam::aws:policy/AdministratorAccess &lt;span class="se"&gt;\&lt;/span&gt;
    aws://&amp;lt;account&amp;gt;/&amp;lt;region&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Then, did
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx cdk deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On the last step of the pipeline: checked that IAM Role for CFN deployment stack had AdminAccess policy in the role.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-github.html" rel="noopener noreferrer"&gt;Create GitHub/BitBucket connection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cdk/latest/guide/cdk_pipeline.html" rel="noopener noreferrer"&gt;CDK Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Reflections on Passing AWS Solutions Architect Associate Exam</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Tue, 12 Oct 2021 06:21:11 +0000</pubDate>
      <link>https://dev.to/aws-builders/reflections-on-passing-aws-solutions-architect-associate-exam-10e0</link>
      <guid>https://dev.to/aws-builders/reflections-on-passing-aws-solutions-architect-associate-exam-10e0</guid>
      <description>&lt;p&gt;&lt;em&gt;With the distribution of remote work, one has more time for personal and career development. Since winter 2020, I have been working entirely remotely. It gave the enormous possibilities to excel career-wise also.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Cloud certifications are significant in terms of structuring the knowledge and improving it. &lt;br&gt;
I started with AWS in 2018 with the corporate program for upskilling the employees by nurturing the program of certification. &lt;br&gt;
With zero experience back then, I passed the &lt;a href="https://igorsoroka.medium.com/how-i-passed-aws-certified-developer-associate-exam-44085cec18b9"&gt;AWS Developer Associate exam&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Community
&lt;/h3&gt;

&lt;p&gt;People are social creatures. That is why we need to go and do something together. I did my first certificate with my peers from the big company. Many people also did the same studies. Most of them had zero or minimal knowledge of the AWS ecosystem. The atmosphere was very supportive.&lt;/p&gt;

&lt;p&gt;This time I studied alone with no extrinsic motivation like extra cash to the salary because of my contracting endeavors. However, I have created a challenge with a couple of people from the community. There we were posting every day about the actions for the studying. It was looking like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Watching lecture on Cloud Guru about Load Balancers - 30 minutes #dayN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consistency and Passive Learning
&lt;/h3&gt;

&lt;p&gt;I had doubts in the middle of the challenge that it would work. But the everyday work on the topics related to the exam helped to be in the context. Our brain is wired to like repetitive things. &lt;/p&gt;

&lt;p&gt;Another point relates to the idea of learning when one is not focused primarily on the task. During this certification, I studied more while doing my jogging routine or driving. If the topic is familiar to the person, it will be beneficial to listen without watching. I think summary videos of ACloudGuru courses were helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Big Picture
&lt;/h3&gt;

&lt;p&gt;The questions in the Solutions Architect exam are more scenario-based. I have experience with passing the Developer one. It is important not only how to use services in combination. The key for passing is to look at the interaction between the elements together with the technical requirements.&lt;/p&gt;

&lt;p&gt;For the practice in architecting, it would be great to watch short videos on the various topics (&lt;a href="https://aws.amazon.com/architecture/this-is-my-architecture."&gt;This is my architecture&lt;/a&gt;). At least, it gives the idea of how to think in scenarios and particular situations. Exam-wise, practice tests are helping for solving cases. The official one from the AWS itself or Udemy ones.&lt;/p&gt;

&lt;h3&gt;
  
  
  My tips on passing the exam
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Course on preparation - ACloudGuru or CloudAcademy&lt;/li&gt;
&lt;li&gt;Focus on practical knowledge

&lt;ul&gt;
&lt;li&gt;QwikLabs&lt;/li&gt;
&lt;li&gt;Above mentioned cloud schools&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Topics: VPC (very important to know how to set up end-to-end), On-premises migration and integration, Storage options for S3, EBS/EFS difference and types, Auto-scaling groups, EC2 types usage scenarios&lt;/li&gt;
&lt;li&gt;Practice Exams (Udemy course or &lt;a href="https://www.amazon.com/dp/111950421X/"&gt;book&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>beginners</category>
      <category>certificate</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Five Dysfunctions of Serverless Development</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Thu, 07 Oct 2021 06:38:43 +0000</pubDate>
      <link>https://dev.to/aws-builders/the-five-dysfunctions-of-serverless-development-1mlp</link>
      <guid>https://dev.to/aws-builders/the-five-dysfunctions-of-serverless-development-1mlp</guid>
      <description>&lt;p&gt;&lt;em&gt;Function as a Service gives magnificent power for shipping software faster without operational overhead. AWS Lambda is a service which used in e-commerce, healthcare, fin-tech, and other industries. Corporations and startups are jumping into the train of the Serverless movement.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The technology advantages always come with hiccups. During my day-to-day work in different teams, I have noticed multiple issues with the development process while using AWS Lambda and related Serverless stack. In this article, I will mention few ones from my practice. There will be solutions that could help to avoid these issues. Disclaimer: I would mostly talk about my experience with the NodeJS ecosystem.&lt;/p&gt;

&lt;p&gt;Top issues with AWS Lambda Development:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Package size&lt;/li&gt;
&lt;li&gt;Too much focus on Local running&lt;/li&gt;
&lt;li&gt;One function has all routing inside (like express)&lt;/li&gt;
&lt;li&gt;Too long function timeout&lt;/li&gt;
&lt;li&gt;Fear of vendor-locking&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Package Size
&lt;/h2&gt;

&lt;p&gt;Lambda function is sent as ZIP to the AWS. When one uses AWS SDK and native language features, there are no problems. In the case of NodeJS, the function which calls the third-party REST API endpoint will have approximately 500 bytes. In a real project, it is not enough to have just one call. In most cases, there is a need for other dependencies.&lt;/p&gt;

&lt;p&gt;The real-life scenario can be like that. The project has started, the business needs results. In the first sprint, the development team took the stories. It is going fine. Now there is 5th one. The CI/CD pipeline became quite slow, the Lambda AWS console is not showing the code and every lambda deployment has all the code for the whole project. The code could easily be up to 20 MBs now. This size is not worth it. Uploading this amount of data is a waste of resources and time.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to avoid this? 
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use code bundler like webpack. It will pack all the external dependencies into one file. It can be handy to minimize your functions. &lt;/li&gt;
&lt;li&gt;Use lambda layers. It will help to put all the needed node_modules into separate packages keeping Lambda small in size. The advantage can be that common dependency like 'axios' could be shared between various lambda functions with no extra costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first approach is the one I have been used, but the latter one looks promising. I am planning to try it at some point. I have not seen it to be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Too much focus on Local running
&lt;/h2&gt;

&lt;p&gt;It is quite common to use SAM with the Serverless app. It provides this great feature of running your lambdas locally. Sounds cool, but in most cases, it would not help you to achieve an error-prone solution.&lt;/p&gt;

&lt;p&gt;Running in the local environment won't save you from the problems with existing infrastructure. In the case of serverless, it is relatively easy to set up multiple environments with lambdas calling other AWS services. For example, it is much faster to deploy and test on the cloud than doing so with local dynamo DB tables.&lt;/p&gt;

&lt;p&gt;My latest successful backend project had Lambdas, Dynamo DB table, SQS queues. We were using the approach where all parts were divided into lambda functions, services, and connectors. Unit tests covered the code by these parts. When there was a need to see functionality working, the test branch could cover it without issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Lambda - serves it all
&lt;/h2&gt;

&lt;p&gt;There is a temptation for Node developers to take the Express application and 'decouple' it with Lambda. I think this is a bad idea. For example, one needs a CRUD application backed by API. Many people would prefer to start by initializing the express app and putting all routes into it.&lt;/p&gt;

&lt;p&gt;In the end, this attempt will be the issue of having a code-heavy lambda function. It will be like a multitool or 'All-in-one' package. 'Fat' lambdas are hard to test and follow when something goes wrong, which is always mysteriously happening.&lt;/p&gt;

&lt;p&gt;I like to think about lambdas as atoms or nanoservices. Just do one call to the third-party API or AWS service with the logic in it. When there is a case of multiple actions, consider switching to more event-driven architecture.&lt;/p&gt;

&lt;h3&gt;
  
  
  Decoupling Ideas
&lt;/h3&gt;

&lt;p&gt;Possible ways could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQS/SNS for scale&lt;/li&gt;
&lt;li&gt;Step Functions for less frequent jobs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Loooooong timeouts
&lt;/h2&gt;

&lt;p&gt;There is no need to have a function with a timeout of 30 seconds that will finish its execution in 10 seconds. It is a good idea to change it at some point in time after the deployment. This action saves money at scale and computing power. One could call it responsible cloud computing when one is not trying to get all the resources but having only needed ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vendor-locking fear
&lt;/h2&gt;

&lt;p&gt;Teams and companies tend to be afraid of this word. In my opinion, they rely too much on multi-cloud. Serverless will lock you to the provider. It is not an issue now because AWS has all you need. Of course, there is a risk that the company will choose another public cloud. However, it is too much effort to do so.&lt;/p&gt;

&lt;p&gt;The teams that are using the Lambdas will most likely use API Gateway, DynamoDB, and SQS. It is not worth it to migrate after a while because of the effort needed for a change. Many teams have been happily using one public cloud for years.&lt;br&gt;
There are companies out there that had started to use AWS Lambda in 2014 when it first appeared. If they need container workloads - they use Fargate with ECS. Maybe Kubernetes is not required on every use case, they think. It comes to a mindset.&lt;/p&gt;




&lt;p&gt;This is an excellent practice to be aware of the issues mentioned in this article because it will save time for the future. These dysfunctions are the ones I encountered in my serverless-related projects. Do you have any bad practices from your experience?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am an AWS Community Builder writing about AWS, CDK, Infrastructure-as-Code, Serverless, and Node development. There is one more article about &lt;a href="https://dev.to/grenguar/my-learnings-after-moving-from-cloudformation-to-cdk-cin"&gt;lessons I learned after switching from CloudFormation to CDK&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>api</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to build Serverless API with database using AWS CDK</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Mon, 27 Sep 2021 08:09:18 +0000</pubDate>
      <link>https://dev.to/grenguar/how-to-build-serverless-api-with-database-using-aws-cdk-4i2d</link>
      <guid>https://dev.to/grenguar/how-to-build-serverless-api-with-database-using-aws-cdk-4i2d</guid>
      <description>&lt;p&gt;&lt;em&gt;Serverless gives us tremendous opportunities to ship new digital products faster at no cost in the beginning. The most classical way of using serverless is to have API backed by AWS Lambdas. This blog will guide the provision and deployment of an application using AWS CDK version 2. However, when I have started implementing it, issues started to appear. I would tell about them while depicting the process and code. Serverless will give the ability to have a full API setup for free.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;First of all, what are we building? It will be an API Gateway backed by AWS Lambdas. They will be reading and writing items to the DynamoDB table. So, here we are, creating the CRUD with REST API. One can find the GitHub repository &lt;a href="https://github.com/Grenguar/aws-cdk-api-workshop" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;&lt;code&gt;API Gateway -&amp;gt; AWS Lambda -&amp;gt; DynamoDB&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Reading is great for many things. So our items will be books! The model will be like that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"name of the book&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;author of the book&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"yearPublished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;published year of the book&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"isbn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;universal identifier of the book&amp;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;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;In this demo application, we are using Dynamo DB. It is a NoSQL database where AWS manages infrastructure. It is working like a magic spell with the Lambda functions. This app will do classic CRUD operations.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DocumentClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk/clients/dynamodb&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;Book&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../models/book&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="nx"&gt;uuid&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;DocumentClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&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;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Book&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;book&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;dbResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Item&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 start will be related to the writing items to the table. Typescript allows having a strongly typed object. The only thing which will be great to have as unique as possible is UUID. In this case, getting a book by the ID will be straightforward. The deleting operation will be very similar.&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;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&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;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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dbResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dbResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deleteItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&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;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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&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;It would be great also to check the created items. Here I am using the 'Scan' operation, which goes through the whole table. For demo purposes, this should be enough. Whenever possible, one should use 'Query.'&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;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DocumentClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ItemList&lt;/span&gt;&lt;span class="o"&gt;&amp;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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;table&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;dbResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dbResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;dbResponse&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cannot get all books&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most complicated request is to update the book from the database. It needs to have parameters and values to edit.&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;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;table&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;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;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Book&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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&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;:title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:author&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:yearPublished&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yearPublished&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:isbn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isbn&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;UpdateExpression&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SET title = :title, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;author = :author, yearPublished = :yearPublished, isbn = :isbn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;ReturnValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATED_NEW&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;dynamo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&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;Dependency injection is the first complication that is happening with lambdas. If one packs it to the AWS by using CDK or CloudFormation, there will be no dependencies. I am using typescript in the project, so in theory, running will create a working js file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; typescript
tsc init
tsc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, it is not so straightforward. There are two issues here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;packing additional files with functionality because having Lambda with the implementation inside one file is a bad practice&lt;/li&gt;
&lt;li&gt;packing external dependencies. In our case, it will be UUID one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I tried to pack just src/functions/create. Running Lambda will give that:&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%2Flyo4n0h4mqn4rx2d0hvy.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%2Flyo4n0h4mqn4rx2d0hvy.png" alt="CloudWatch error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That is why the next logical step will be to find out how to pack Lambda code together with dependencies and don't upload 100 Mb of node_modules. I decided to use webpack for that. It does the job right and will allow running just this command after installation: &lt;code&gt;webpack&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Lambdas' main handler functions will be as simple as calling the DynamoDB file with the needed operations. For example, creating the item would be like that.&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEventV2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-lambda&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;create&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../connectors/dynamo-db-connector&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEventV2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bookItem&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createBook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;table&lt;/span&gt; &lt;span class="k"&gt;as&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;bookItem&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request body is empty!&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One could find handlers for other operations in the &lt;a href="https://github.com/Grenguar/aws-cdk-api-workshop/tree/main/src/functions" rel="noopener noreferrer"&gt;repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure
&lt;/h2&gt;

&lt;p&gt;As previously mentioned, CDK will be in charge of the infrastructure provisioning. I will be using just one stack with DynamoDB, 5 Lambdas, Rest API, permissions for table connections, and integrations for endpoints. We will put the infrastructure application in a separate folder /infra.&lt;/p&gt;

&lt;p&gt;To create DynamoDB with Lambda calling it, one will need ready-made typed constructs for DynamoDB, Lambda, and permissions. The code is situated one level above, so it is essential to put it like this. The good thing here is that CDK will error when one calls the template's 'synthesizing' with the wrong parameters. After that, Lambda will need a permission to put an item to DynamoDB. One could do this by adding one line of code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamoTable&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;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Table&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;BookTable&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;tableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;BookStorage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;readCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;writeCapacity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;partitionKey&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;id&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;ddb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AttributeType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;STRING&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createBookFunction&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;lambda&lt;/span&gt;&lt;span class="p"&gt;.&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;CreateHandler&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;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_14_X&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;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="nf"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../code&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="s1"&gt;create.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;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;table&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dynamoTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tableName&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;logRetention&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RetentionDays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ONE_WEEK&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;dynamoTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;grant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createBookFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dynamodb:PutItem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, the function could be attached to the API. First, we are initializing RestAPI. Then, we add a resource to root for having a path like POST /.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&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;apigw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RestApi&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="s2"&gt;`BookAPI`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;restApiName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`book-rest-api`&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;mainPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;books&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createBookIntegration&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;apigw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;createBookFunction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;mainPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createBookIntegration&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The steps shown in this section will be repeated for other endpoints also. The best part comes when one can see that lambda creation is the same but with different parameters. CDK could wrap it into the function for saving space and having reusable code for provisioning handlers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing endpoints
&lt;/h2&gt;

&lt;p&gt;After the manipulations mentioned in the previous sections, we can try out the API mentioned in this article. Let's start with the list of all books. The result should be empty.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="s1"&gt;'https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/books'&lt;/span&gt;
RESPONSE:
Status: 200
&lt;span class="o"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, let's create a couple of books.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s1"&gt;'https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/books'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
"title": "Life of PI",
"author": "Yann Martel",
"yearPublished": "2000",
"isbn": "0-676-97376-0"
}'&lt;/span&gt;

RESPONSE:
Status: 201
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And one more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s1"&gt;'https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/books'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
"title": "Simulacra and Simulation",
"author": "Jean Baudrillard",
"yearPublished": "0-472-06521-1",
"isbn": "0-676-97376-0"
}'&lt;/span&gt;

RESPONSE:
Status: 201
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can call a list to make sure that all the books are in their places.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; GET &lt;span class="s1"&gt;'https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/books'&lt;/span&gt;

RESPONSE:
Status: 200
&lt;span class="o"&gt;[{&lt;/span&gt;
   &lt;span class="s2"&gt;"isbn"&lt;/span&gt;: &lt;span class="s2"&gt;"0-676-97376-0"&lt;/span&gt;,
   &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"617d6b3e-ce6d-4e8d-a10f-05d6703ad7ac"&lt;/span&gt;,
   &lt;span class="s2"&gt;"yearPublished"&lt;/span&gt;: &lt;span class="s2"&gt;"2000"&lt;/span&gt;,
   &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Life of PI"&lt;/span&gt;,
   &lt;span class="s2"&gt;"author"&lt;/span&gt;: &lt;span class="s2"&gt;"Yann Martel"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;, &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="s2"&gt;"isbn"&lt;/span&gt;: &lt;span class="s2"&gt;"0-676-97376-0"&lt;/span&gt;,
   &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"2a8251ee-73ee-4717-8f6f-0f11dd2b861f"&lt;/span&gt;,
   &lt;span class="s2"&gt;"yearPublished"&lt;/span&gt;: &lt;span class="s2"&gt;"0-472-06521-1"&lt;/span&gt;,
   &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Simulacra and Simulation"&lt;/span&gt;,
   &lt;span class="s2"&gt;"author"&lt;/span&gt;: &lt;span class="s2"&gt;"Jean Baudrillard"&lt;/span&gt;
&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lambda added the books, and a listing is also working. However, there is an error in the database. I noticed that 'Life of PI' was published in 2001 and not in 2000. So, we need to call the update endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; PUT &lt;span class="s1"&gt;'https://y55xcv8jmc.execute-api.eu-west-1.amazonaws.com/prod/books/617d6b3e-ce6d-4e8d-a10f-05d6703ad7ac'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;'{
  "isbn": "0-676-97376-0",
  "yearPublished": "2001",
  "title": "Life of PI",
  "author": "Yann Martel"
}'&lt;/span&gt;

Status: 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another list call will show that the book was successfully updated.&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="o"&gt;[{&lt;/span&gt;
  &lt;span class="s2"&gt;"isbn"&lt;/span&gt;: &lt;span class="s2"&gt;"0-676-97376-0"&lt;/span&gt;,
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"617d6b3e-ce6d-4e8d-a10f-05d6703ad7ac"&lt;/span&gt;,
  &lt;span class="s2"&gt;"yearPublished"&lt;/span&gt;: &lt;span class="s2"&gt;"2001"&lt;/span&gt;,
  &lt;span class="s2"&gt;"author"&lt;/span&gt;: &lt;span class="s2"&gt;"Yann Martel"&lt;/span&gt;,
  &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Life of PI"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;, &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"isbn"&lt;/span&gt;: &lt;span class="s2"&gt;"0-676-97376-0"&lt;/span&gt;,
  &lt;span class="s2"&gt;"id"&lt;/span&gt;: &lt;span class="s2"&gt;"2a8251ee-73ee-4717-8f6f-0f11dd2b861f"&lt;/span&gt;,
  &lt;span class="s2"&gt;"yearPublished"&lt;/span&gt;: &lt;span class="s2"&gt;"0-472-06521-1"&lt;/span&gt;,
  &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Simulacra and Simulation"&lt;/span&gt;,
  &lt;span class="s2"&gt;"author"&lt;/span&gt;: &lt;span class="s2"&gt;"Jean Baudrillard"&lt;/span&gt;
&lt;span class="o"&gt;}]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's delete one of the books by calling the DELETE endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--location&lt;/span&gt; &lt;span class="nt"&gt;--request&lt;/span&gt; DELETE &lt;span class="s1"&gt;'https://&amp;lt;api-id&amp;gt;.execute-api.&amp;lt;region&amp;gt;.amazonaws.com/prod/books/2a8251ee-73ee-4717-8f6f-0f11dd2b861f'&lt;/span&gt;
Status: 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After calling it multiple times with different ids, one will get empty response for the list of books. This is what we are expecting here.&lt;/p&gt;




&lt;p&gt;In this article, I showed how to deploy Serverless API with the NoSQL Database using AWS Lambda, DynamoDB, and API Gateway deployed by CDK. Lambdas have all permissions for CRUD operations. This can be a sample project for a more complicated setup. Also, I was using the webpack to have all the node dependencies in place. The future work will include the CodePipeline for CI/CD connected to the GitHub hook. Thanks for reading this article! &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Want to learn more about AWS, Serverless, and CDK? Subscribe to my blog where I am posting about these topics on a regular basis.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>aws</category>
      <category>api</category>
      <category>devops</category>
    </item>
    <item>
      <title>My lessons after moving from CloudFormation to CDK</title>
      <dc:creator>Igor Soroka</dc:creator>
      <pubDate>Wed, 15 Sep 2021 07:04:06 +0000</pubDate>
      <link>https://dev.to/grenguar/my-learnings-after-moving-from-cloudformation-to-cdk-cin</link>
      <guid>https://dev.to/grenguar/my-learnings-after-moving-from-cloudformation-to-cdk-cin</guid>
      <description>&lt;p&gt;&lt;em&gt;Nowadays there is no doubt that 'Infrastructure as real code' is a way of cloud resources provisioning. CDK is an incredible way of doing this in the AWS ecosystem. This article will talk about the situation when the Cloudformation template is in place and you want to make a new setup with the CDK using Typescript. The opinions are my own.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Case
&lt;/h2&gt;

&lt;p&gt;Let's imagine you have a new project in a team where CFN was used for a long time. There is a lot of boilerplate already and people are repeating the same things over and over again. There is also some custom CI/CD setup in place. With this background - you are set to start a new project with CDK.&lt;/p&gt;

&lt;p&gt;Excited? Me too. But there are some complications because CFN is a YAML/JSON-based templating mechanism. CDK in short is an abstraction on top of CFN which is using a programming language for provisioning infrastructure in a structured way. Here are my tips on how to start switching from Cloudformation/SAM after using the tool for almost a year now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with a small project
&lt;/h2&gt;

&lt;p&gt;Consider a project without many elements. Try to avoid projects where you need to set up VPC by yourself. Also, it will be better to avoid projects with container orchestrations using ECS or Kubernetes. The ideal first project will be the one having S3, Lambda, CloudFront, API Gateway, DynamoDB, and IAM permissions. Example projects can be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scheduled event placing data into S3/DynamoDB&lt;/li&gt;
&lt;li&gt;Event from Github/Bitbucket &lt;/li&gt;
&lt;li&gt;The API call to do some simple job like routing request to another party.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another important point is to use CDK version 2. x. In most of the guides, it will be suggested to utilize the first one. It is outdated and has many dependencies issues. The developing experience will be much more delightful. For installing it -  run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install cdk@next
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Study CDK basic concepts
&lt;/h2&gt;

&lt;p&gt;There are multiple important terms when it comes to CDK. The first one is 'App'. It is the root element of the structure. There you can describe the stacks and their creation.&lt;br&gt;
The most interesting concept is a construct. From AWS docs:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Constructs are the basic building blocks of AWS CDK apps. A construct represents a "cloud component" and encapsulates everything AWS CloudFormation needs to create the component.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is basically a module of the resources packed together as a logical unit. The constructs are having different levels of abstraction. There are ones that are the closest to the CloudFormation. Typically, they have poor typing. &lt;/p&gt;

&lt;p&gt;There are 3 levels of abstraction: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CFN resources  - they are mapped to the underlined CFN resources.&lt;/li&gt;
&lt;li&gt;Level 2  - they give the abstractions and typing. The constructs can be also coming from the library here. Many constructs will allow having types and making fewer mistakes.&lt;/li&gt;
&lt;li&gt;Level 3 - these are the whole patterns. They can be done by AWS or other developers. The ones coming from AWS advocates and heroes could be found here.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From my point of view, the power of CDK lies in the third level. It gives the possibility to automate the creation of very common patterns in your team. For example, it can be a custom domain or pipeline setup. &lt;/p&gt;

&lt;h2&gt;
  
  
  Planning the stacks
&lt;/h2&gt;

&lt;p&gt;Another important point is to have an idea of how many stacks will you need to succeed in the provisioning of the infrastructure. One stack is not helpful in many cases. It means that stacks should be architecture in a way that each of them solves one problem. It can be an issue to determine whether to use the construct or the stack.&lt;/p&gt;

&lt;p&gt;According to AWS documentation: "A stack is a collection of AWS resources that you can manage as a single unit." When you have an API with Lambdas - this can be a stack. However, if you have databases and other types of storage - this can be another stack. &lt;/p&gt;

&lt;p&gt;One more thing which comes quite often, in the end, is how the stacks will talk with each other. There are multiple ways of doing this. You can either pass general props or the whole stack as an input to the next one, for example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Always check original documentation
&lt;/h2&gt;

&lt;p&gt;The CDK is just awesome, from my point of view. But it is not saving us from reading and understanding Cloudformation. De-facto CDK is synthesizing the CloudFormation template in JSON format. Thus, it is obligatory to see what it is doing for us.&lt;/p&gt;

&lt;p&gt;There are great tricks hidden in the official documentation when you are actually reading it. Most of the time, I am googling something like 'AWS::DynamoDB::Table'. The response will give the needed documentation page for the infrastructure element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failures are essential
&lt;/h2&gt;

&lt;p&gt;My journey with CDK started with the failure of deployment when I tried to have an S3 bucket created. It took 15 minutes to deploy it with no success. It is ok to fail with CDK in the beginning. Do not try to hurry and migrate the whole application at once. &lt;/p&gt;

&lt;p&gt;During one of the projects, I had a CI/CD setup done with SAM and CloudFormation. Migration of it completely to CDK would take time from the actual feature development. So the solution was to migrate the implementation code infrastructure to CDK and rest the pipeline with the same setup. I learned a lot during this transition for the next project where I took the whole infrastructure into CDK.&lt;/p&gt;




&lt;p&gt;All in all, CDK is worth to be tried on the next PoC or internal tool because it gives the real coding experience while doing infrastructure. This is especially important when you are going to use a DevOps mindset for the new features where engineers are responsible for not only the implementation. Usage of the same language for the IaC tool eliminates the context switching between TypeScript and YAML. Thus, it will increase the productivity of the whole team.&lt;/p&gt;

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