<?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: Vinh Le</title>
    <description>The latest articles on DEV Community by Vinh Le (@vinhle95).</description>
    <link>https://dev.to/vinhle95</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%2F52184%2F8bdbc514-f6ee-455e-847e-b07aae3ae95f.jpg</url>
      <title>DEV Community: Vinh Le</title>
      <link>https://dev.to/vinhle95</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinhle95"/>
    <language>en</language>
    <item>
      <title>Learn AWS EC2 by deploying a NodeJS application (P2)</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Sun, 05 Jul 2020 06:21:57 +0000</pubDate>
      <link>https://dev.to/vinhle95/learn-aws-ec2-by-deploying-a-nodejs-application-p2-28j4</link>
      <guid>https://dev.to/vinhle95/learn-aws-ec2-by-deploying-a-nodejs-application-p2-28j4</guid>
      <description>&lt;h1&gt;
  
  
  Part 2: Run a NodeJS application on an EC2 instance
&lt;/h1&gt;

&lt;p&gt;In the &lt;a href="https://blog.vinhlee.com/ec2/"&gt;previous part&lt;/a&gt; of this blog, we have learnt to create and SSH to an EC2 instance. In this part, we will setup and run a NodeJS server on it 😎&lt;/p&gt;

&lt;p&gt;Let's split the work into 3 smaller tasks. First of all, we need to configure our instance to accept traffics coming to Node server's port. Next, after installing &lt;code&gt;nvm&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt;, we will clone the source code and get the server running.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit Inbound Rules to accept traffic from server port
&lt;/h2&gt;

&lt;p&gt;Let's add another security group for this purpose. This is pretending that our Node server will run on port 3000.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;MyInstance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
  &lt;span class="s"&gt;SecurityGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- !Ref NodeServerGroup&lt;/span&gt;
  &lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="na"&gt;NodeServerGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
  &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NodeServer&lt;/span&gt;
    &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow traffics to instance in port &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;
    &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
      &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
      &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Install &lt;code&gt;nvm&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; to the instance
&lt;/h2&gt;

&lt;p&gt;First, we need to SSH to the instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; &amp;lt;pem-key-name.pem&amp;gt; ec2-user@&amp;lt;public_ip_v4&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If the instance asks you to run any updates, go ahead and do so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next, we need to install &lt;code&gt;nvm&lt;/code&gt; in our instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o-&lt;/span&gt; https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
&lt;span class="nb"&gt;.&lt;/span&gt; ~/.nvm/nvm.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's verify if &lt;code&gt;nvm&lt;/code&gt; has been successfully installed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We could then install &lt;code&gt;node&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;node
...
node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Clone Git repository
&lt;/h2&gt;

&lt;p&gt;Let's make a Node Express app and push it to GitHub so that we could clone the source code to our instance. I have made a dead simple one that you might use as a reference: &lt;a href="https://github.com/vinhlee95/express-ec2"&gt;vinhlee95/express-ec2&lt;/a&gt;. Keep in mind that you will &lt;em&gt;have to&lt;/em&gt; create your own repository to add SSH key generated in EC2 instance to your settings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate a SSH key in EC2 instance
&lt;/h3&gt;

&lt;p&gt;We could do that by this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After following the instructions (remember to note down the passphrase), you should have a SSH key in place. Let's get it and add to GitHub settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_rsa
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Your newly generated SSH key will be shown in the Terminal. Copy it and and it in your GitHub SSH settings (Settings -&amp;gt; SSH and GPG keys -&amp;gt; New SSH key).&lt;/p&gt;

&lt;h3&gt;
  
  
  Clone the source code
&lt;/h3&gt;

&lt;p&gt;After having the SSH key saved, you should be able to clone your application's source code to EC2 instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:your-repo.git
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After it is done, you should see application's code under your current directory:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0LiRV80j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/syilj79zmpe31n4wyab3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0LiRV80j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/syilj79zmpe31n4wyab3.png" alt="cloned source code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install dependencies and run the Node server
&lt;/h3&gt;

&lt;p&gt;Let's first install all of dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We will use &lt;a href="https://www.npmjs.com/package/pm2"&gt;pm2&lt;/a&gt; - a Node process manager to start our server. Let's install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
...
pm2 &lt;span class="nt"&gt;-v&lt;/span&gt;
pm2 start app.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RuPjsfZR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jk4pcyg3qj5of5h9x4dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RuPjsfZR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/jk4pcyg3qj5of5h9x4dg.png" alt="pm2 start"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our server should be running now 🥂 Let's show server's logs in the terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;pm2 log
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--42LQeSzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r64earlc9vh5ayskndg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--42LQeSzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/r64earlc9vh5ayskndg8.png" alt="pm2 log"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cheers! Things are working now. Let's test it by open the instance's public DNS in the browser! You could get the URL in &lt;em&gt;Description&lt;/em&gt; section in the bottom of AWS EC2's console. Remember that we need to specify our server's running port in the URL as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fvc9tDjX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c7o7km1n88epb4qtsh09.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fvc9tDjX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/c7o7km1n88epb4qtsh09.png" alt="instance DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Congrats! Your instance is running a Node.js server now 😎
&lt;/h2&gt;

&lt;p&gt;Note that you might want to delete CloudFormation stack after done playing around to avoid any extra charge from AWS 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's sum up what we have done to make it happen:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Configure EC2's instance Inbound rules to accept traffic from server port.&lt;/li&gt;
&lt;li&gt;Install &lt;code&gt;nvm&lt;/code&gt; and &lt;code&gt;node&lt;/code&gt; in the instance&lt;/li&gt;
&lt;li&gt;Use Git to clone source code to the instance. In order to do that in the Linux instance, we need to:

&lt;ul&gt;
&lt;li&gt;Generate SSH key in the instance and add it to GitHub settings&lt;/li&gt;
&lt;li&gt;Install Git and clone the repo&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Install app's dependencies along with PM2&lt;/li&gt;
&lt;li&gt;Run the Node.js server&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>node</category>
      <category>backend</category>
    </item>
    <item>
      <title>Learn AWS EC2 by deploying a NodeJS application</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Tue, 23 Jun 2020 03:59:59 +0000</pubDate>
      <link>https://dev.to/vinhle95/learn-aws-ec2-by-deploying-a-nodejs-application-2efd</link>
      <guid>https://dev.to/vinhle95/learn-aws-ec2-by-deploying-a-nodejs-application-2efd</guid>
      <description>&lt;h1&gt;
  
  
  Part 1: Create and SSH to an EC2 instance
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is EC2
&lt;/h2&gt;

&lt;p&gt;Elastic Compute Cloud (EC2) is an AWS's service providing compute capacity in the cloud. To make it simple, EC2 is the environment where your front-end, back-end,... applications live and run.&lt;/p&gt;

&lt;p&gt;We are all aware that each application has different architectures and yours may run in a container one like Docker. However, at the end of the day, your Docker application will be run on an EC2 instance even if you might host your docker image in Elastic Container Repository (ECR) and use Elastic Container Service (ECS) to deploy and manage it.&lt;/p&gt;

&lt;p&gt;Similarly, a static front-end React application, a server side NodeJS application could run on EC2 instances (S3 may be a better and simpler place for hosting static front-end apps). In AWS ecosystem, you will get to know more resources and services that &lt;em&gt;make it easier&lt;/em&gt; deploying your application. However, EC2 is the popular final destination that those services deploy applications to.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an EC2 instance?
&lt;/h3&gt;

&lt;p&gt;An EC2 instance is a virtual server that could run an application program in Amazon's EC2 computing environment. You could create an EC2 instance via AWS console, CLI or templates. In this blog, I will show you how to do it via a CloudFormation template.&lt;/p&gt;

&lt;p&gt;Ok, so there is no more cumbersome theory, let's see how EC2 look and work in action! 👨🏻‍💻😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an EC2 instance via CloudFormation template
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📌 Prerequisite
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Have an AWS account&lt;/li&gt;
&lt;li&gt;Already installed AWS CLI in your local machine and add configuration for region, access key and secret key&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could refer to &lt;a href="https://blog.vinhlee.com/iam/"&gt;AWS IAM blog&lt;/a&gt; for setup guide.&lt;/p&gt;

&lt;p&gt;You could also check if the configuration has been done by checking in Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aws &lt;span class="nt"&gt;--version&lt;/span&gt;
aws-cli/2.0.11 Python/3.7.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure
AWS Access Key ID &lt;span class="o"&gt;[&lt;/span&gt;your_configured_access_key]:
AWS Secret Access Key &lt;span class="o"&gt;[&lt;/span&gt;your_configured_secret_key]:
Default region name &lt;span class="o"&gt;[&lt;/span&gt;your_configured_region]:
Default output format &lt;span class="o"&gt;[&lt;/span&gt;json]:
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Create CloudFormation template
&lt;/h3&gt;

&lt;p&gt;CloudFormation is a declarative way to outline AWS infrastructure. Meaning you could define and configure resources in 1 template. AWS will take care of the rest (hard work) and create all of these defined services in the cloud.&lt;/p&gt;

&lt;p&gt;The reason why I prefer CloudFormation instead of walking through step-by-step in AWS console GUI is because it is fairly straightforward. You could also easily pick up my template and we are sure to be on the same place 🥂&lt;/p&gt;

&lt;p&gt;CloudFormation could be written in &lt;code&gt;yaml&lt;/code&gt; or &lt;code&gt;json&lt;/code&gt; formats. I am more keen on &lt;code&gt;yaml&lt;/code&gt; due to its better readability.&lt;/p&gt;

&lt;p&gt;In your project directory, create a file named &lt;code&gt;ec2.yaml&lt;/code&gt;. We will add all of our EC2 instance's configuration here.&lt;/p&gt;

&lt;p&gt;Add following configuration to your &lt;code&gt;yaml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;MyInstance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Instance&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eu-north-1a"&lt;/span&gt;
      &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ami-0c5254b956817b326"&lt;/span&gt;
      &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;t3.micro"&lt;/span&gt;
      &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ec2-general"&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;HTTPSecurityGroup&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;SSHSecurityGroup&lt;/span&gt;

  &lt;span class="c1"&gt;# Elastic IP for the instance&lt;/span&gt;
  &lt;span class="na"&gt;MyEIP&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::EIP&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;InstanceId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;MyInstance&lt;/span&gt;

  &lt;span class="na"&gt;SSHSecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SSHSecurityGroupStack&lt;/span&gt;
      &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Enable SSH access to instances via port &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
        &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
        &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
        &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;

  &lt;span class="na"&gt;HTTPSecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;EC2CFHTTPGroup&lt;/span&gt;
      &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow HTTP traffics to instance in port &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
        &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
        &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
        &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You could find this template in this &lt;a href="https://gist.github.com/vinhlee95/d125be62a3228cec8c60d5578287a050"&gt;gist&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;The most important part that we need to focus in scope of this blog is our instance resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;MyInstance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Instance&lt;/span&gt;
  &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;eu-north-1a"&lt;/span&gt;
    &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ami-0c5254b956817b326"&lt;/span&gt;
    &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;t3.micro"&lt;/span&gt;
    &lt;span class="na"&gt;KeyName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ec2-general"&lt;/span&gt;
    &lt;span class="na"&gt;SecurityGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;HTTPSecurityGroup&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;SSHSecurityGroup&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In here we told AWS to create an EC2 instance in EU north 1a region (Stockholm). &lt;code&gt;ImageId&lt;/code&gt; is id of an Amazon Image Machine (AMI) - our unit of deployment. Each API is an environment that packs up everything our application needs to run.&lt;/p&gt;

&lt;p&gt;Our image id &lt;code&gt;ami-0c5254b956817b326&lt;/code&gt; is configured by AWS to run on Linux platform. It has &lt;code&gt;t3.micro&lt;/code&gt; instance type, which has quite limited resources (CPU, memory, network performance) but serves well for demo purpose (as for the name).&lt;/p&gt;

&lt;p&gt;You could find out more about EC2's instance types &lt;a href="https://aws.amazon.com/ec2/instance-types/"&gt;here&lt;/a&gt;. If you want to use a different AMI, refer to &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/finding-an-ami.html"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload CloudFormation template
&lt;/h3&gt;

&lt;p&gt;Enter this command to your Terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;aws cloudformation create-stack &lt;span class="nt"&gt;--stack-name&lt;/span&gt; ec2-example &lt;span class="nt"&gt;--template-body&lt;/span&gt; file://ec2.yaml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The CLI will notify you if succeeded with a message containing new CloudFormation's stack id. To verify that, you'd need to &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-login.html"&gt;logging in to AWS's console&lt;/a&gt; and select the newly created stack:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AMm7tnYT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4aqabfxkhe15lc3nurrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AMm7tnYT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4aqabfxkhe15lc3nurrk.png" alt="cloudformation stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a key pair to access the instance
&lt;/h3&gt;

&lt;p&gt;First, you need to go to EC2's console. Go to &lt;em&gt;Resources&lt;/em&gt; tab of CloudFormation stack page, you should see an item on the list with &lt;code&gt;MyInstance&lt;/code&gt; logical ID of type &lt;code&gt;AWS::EC2::Instance&lt;/code&gt;. Click the link in its physical ID, you should be able to visit your EC2 console.&lt;/p&gt;

&lt;p&gt;Next, select &lt;code&gt;Key Pairs&lt;/code&gt; under &lt;code&gt;Network &amp;amp; Security&lt;/code&gt; section in left side bar of the console. Click &lt;code&gt;Create key pair&lt;/code&gt; and enter &lt;code&gt;ec2-general&lt;/code&gt; as name. You should make sure that this name is &lt;em&gt;exactly similar&lt;/em&gt; to &lt;code&gt;KeyName&lt;/code&gt; in the CloudFormation template. Leave file format as &lt;code&gt;pem&lt;/code&gt; as default and click create. The new key pair should be downloadable now 🥂&lt;/p&gt;

&lt;p&gt;Another thing you need to note down from the console is the instance's public IPv4. Navigate to &lt;code&gt;Instances&lt;/code&gt; section in the side bar and you could find it in the created instance's description.&lt;/p&gt;

&lt;h3&gt;
  
  
  SSH to your instance
&lt;/h3&gt;

&lt;p&gt;Now you should have the key pair downloaded in your local machine, we will use that as security gateway to connect to EC2 instance via SSH. In our CloudFormation template, we specify this as &lt;code&gt;SSHSecurityGroup&lt;/code&gt; resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;SSHSecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
  &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GroupName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SSHSecurityGroupStack&lt;/span&gt;
    &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Enable SSH access to instances via port &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;
    &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
      &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
      &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
      &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now let's open your Terminal and navigate to directory where the key pair is stored. The next thing to do is to use following command to set permissions of your file so that &lt;em&gt;only you can read it&lt;/em&gt;. Otherwise, you will get &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/TroubleshootingInstancesConnecting.html#troubleshoot-unprotected-key"&gt;&lt;code&gt;Error: Unprotected private key file&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;chmod &lt;/span&gt;400 my-key-pair.pem
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Everything should be ready then! Let's SSH to the instance by this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; my-key-pair.pem ec2-user@&amp;lt;PUBLIC_IP&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Public_IP&lt;/code&gt; is your instance's IPv4 public IP that we noted from the console in the previous section. This is the first time we access the instance so you might be asked to add the instance's address to your known host. Go ahead and accept, your attempt should be success by now 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MNAfFSV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4skx6izwthtd642kpviy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MNAfFSV0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/4skx6izwthtd642kpviy.png" alt="ssh to ec2 instance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you could switch to root user and update security patches for your instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;su
&lt;span class="nb"&gt;sudo &lt;/span&gt;yum update
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Congrats! You made it! 😎🎉 In this first part, we have learnt:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create an EC2 instance with security groups by CloudFormation template.&lt;/li&gt;
&lt;li&gt;Create a Key pair for accessing to the instance&lt;/li&gt;
&lt;li&gt;SSH to your instance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This also brings to the end of this part. In the upcoming part, we will get our hands dirtier running a NodeJS server in the instance. Stay tuned! 🙌&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>node</category>
      <category>server</category>
    </item>
    <item>
      <title>AWS IAM 101</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Sat, 13 Jun 2020 05:56:28 +0000</pubDate>
      <link>https://dev.to/vinhle95/aws-iam-101-51jg</link>
      <guid>https://dev.to/vinhle95/aws-iam-101-51jg</guid>
      <description>&lt;h2&gt;
  
  
  What is IAM
&lt;/h2&gt;

&lt;p&gt;IAM is an essential gate-keeper of Amazon Web Service (AWS). This is the place where we would administer authentication and authorisation for AWS's environments and services.&lt;/p&gt;

&lt;p&gt;Let's imagine an use case where we want to develop a Cloud application using AWS's infrastructure. In order to interact with AWS's API (via command line tool CLI, for instance). We would first need to create a new IAM user. The user then needs to be granted permissions to access to certain resources. How? By attaching specific IAM policies. If we want 2 services communicating to each other, such as EC2 and DynamoDB. We then need to have a valid IAM role, specifically cover those services.&lt;/p&gt;

&lt;p&gt;That single, simple example alone can already tell how important IAM is in AWS ecosystem. In fact, IAM is &lt;em&gt;everywhere&lt;/em&gt;. We will see, interact and configure it all across phases in development, security as well as monitoring.&lt;/p&gt;

&lt;p&gt;IAM is universal and does not apply to regions at the moment. This means we could use &lt;em&gt;global&lt;/em&gt; IAM entities to administer resources throughout all AWS supported regions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building blocks
&lt;/h2&gt;

&lt;p&gt;IAM consists of users, groups, roles and policy documents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Users
&lt;/h3&gt;

&lt;p&gt;Each IAM &lt;strong&gt;user&lt;/strong&gt; has defined permissions to access and control specific AWS resources. When you first created an AWS account, AWS gives you &lt;em&gt;root&lt;/em&gt; account. This user is in "god mode" so it has complete control over everything.&lt;/p&gt;

&lt;p&gt;Is root account the only user we need? Absolutely &lt;strong&gt;NO&lt;/strong&gt;. It is highly recommended to have different users for different applications and more importantly, &lt;em&gt;limit access control&lt;/em&gt; for individual users. Besides, there is a rule of thumb to interact and configure AWS's services through IAM users and never hard-code security credentials such as assess key and secret key.&lt;/p&gt;

&lt;p&gt;For example, a developer in a team should be given accesses only to EC2, S3 and CodeCommit, &lt;strong&gt;definitely not&lt;/strong&gt; Administrator access. Our applications will be more secure that way as no one could cause any harm, unintentionally or deliberately.&lt;/p&gt;

&lt;p&gt;When creating a brand new user (not root user in the first time), we can tell AWS which authentication credentials we want to obtain. There are 2 types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Management Console access: a password that the user will use, along with user name and AWS's account ID, to sign in to AWS Console. The user will then interact with services via AWS's GUI.&lt;/li&gt;
&lt;li&gt;Programmatic access: an access key and a secret key. The user will use those 2 to talk to services via CLI. These keys, especially secret key, are very important and &lt;em&gt;could only be downloaded once&lt;/em&gt; right after creation. It should be therefore saved securely in your local machine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Configure IAM user locally
&lt;/h4&gt;

&lt;p&gt;Let's have a tour setting up an IAM user in your local machine. This is one-time process and your interaction with AWS's CLI later on will use this credential. If you want to configure a different user, repeat following steps with that user's keys.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create AWS's config folder in root directory
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/.aws
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/.aws
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create &lt;code&gt;credential&lt;/code&gt; file for storing access key and secret key
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;credential
vim credential
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here is what you need to save to this file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[&amp;lt;YOUR_USER_NAME&amp;gt;]
aws_access_key_id=&amp;lt;ACCESS_KEY&amp;gt;
aws_secret_access_key=&amp;lt;SECRET_KEY&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create &lt;code&gt;config&lt;/code&gt; file for &lt;code&gt;output&lt;/code&gt; and &lt;code&gt;region&lt;/code&gt; configurations
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;config
vim config
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then add your configuration in the same manner as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[profile &amp;lt;YOUR_USER_NAME&amp;gt;]
region=&amp;lt;YOUR_REGION&amp;gt;
output=json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that specified region here will be used to determine where AWS locates your application's resources. For example, if my region is &lt;code&gt;eu-north-1&lt;/code&gt; and later on I use this configuration to create a S3 bucket via CLI, the bucket will be located in Stockholm. You could go &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html"&gt;here&lt;/a&gt; to see a list of regions that is being supported.&lt;/p&gt;

&lt;h3&gt;
  
  
  Groups
&lt;/h3&gt;

&lt;p&gt;A group is a collection of IAM users. Group is useful when we want to manage permissions for a group of user. Without group, listing permissions for every single user will be a huge hassle. We could grant permissions to a group and then add users to that group. Those added users will then automatically have all of their group's permissions.&lt;/p&gt;

&lt;p&gt;Another point to note is that group is born only to make it simpler to manage user permissions. A group thus does not have security credentials as well as cannot access and manage AWS's resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Roles
&lt;/h3&gt;

&lt;p&gt;An IAM role is an entity that defines a list of permissions to allow a &lt;em&gt;trusted entity&lt;/em&gt; to interact with other AWS's services. That entity could be a service like EC2, Lambda or an AWS's account.&lt;/p&gt;

&lt;p&gt;Creating a new role is similar to delegate access permissions to those trusted entities without having to share access keys. A role cannot make direct requests to AWS services, but the entity it attached to. Keep in mind that you could use IAM roles to delegate access to a &lt;em&gt;different AWS account&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Policies
&lt;/h3&gt;

&lt;p&gt;A policy is the mean to assign permissions to IAM entities(users, groups and roles) so that they could access to AWS services. In other words, an user cannot access an AWS's resource until we attach a valid policy to that user.&lt;/p&gt;

&lt;p&gt;There are 3 types of policies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Managed Policies: created and administered by AWS. Managed policies could be reused between IAM entities and &lt;em&gt;cannot be modified&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Customer Managed Policies: created and used by own users and are reusable across entities similar to the previous one.&lt;/li&gt;
&lt;li&gt;Inline policies: created by user and embedded directly to &lt;em&gt;individual&lt;/em&gt; user, group or role. Inline policies cannot be reused in different IAM entities as it emphasises direct 1-1 relationship between entity and the policy itself. Once the entity is deleted, inline policies attached to it get removed as well.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best practice is to use customer managed policies over others. Because we could assure greatest security by only granting utmost required permissions for the entity to handle specific tasks. Inline policies are least recommended due to its unreusable nature, unless your scenario requires. AWS managed policies are ready-made and easy to use. However, it usually provide broad administrative for general usage and thus is not tailored for specific needs.&lt;/p&gt;

&lt;p&gt;For selecting an AWS managed policy, it is as simple as select 1 item in the list, as long as you know exactly what type of permission you are looking for. For customer managed policies, you need to be aware of 2 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Policies are written in IAM policy language. They are essentially JSON files with a list of &lt;em&gt;statements&lt;/em&gt;. Each statement specifies if an &lt;em&gt;action&lt;/em&gt; is &lt;em&gt;allowed&lt;/em&gt; or &lt;em&gt;denied&lt;/em&gt; for a particular &lt;em&gt;resource&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;You could use either visual editor in AWS console or writing policy JSON file &lt;a href="https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"&gt;on your own&lt;/a&gt; and attach it via CLI.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;IAM manages authentication and authorisation for AWS management console and AWS resources.&lt;/li&gt;
&lt;li&gt;Users, groups, roles and policies are different IAM entities.&lt;/li&gt;
&lt;li&gt;An IAM user could make requests to AWS services directly and has long-term access keys and credentials.&lt;/li&gt;
&lt;li&gt;A group is essentially a management convenience to manage a similar permission set for multiple users.&lt;/li&gt;
&lt;li&gt;An IAM role is a mean to delegate AWS resources's accesses to trusted entities such as AWS services like EC2, Lambda and even a different AWS account.&lt;/li&gt;
&lt;li&gt;To grant specific permissions to an IAM entity, you need to attach a policy to that entity. A policy is a JSON file describes permissions. You could either write your own - customer managed policies, or use pre-made AWS managed policies. The former is recommended as the best practice.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/iam/faqs/"&gt;AWS IAM FAQs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html"&gt;Regions, Availability Zones, and Local Zones&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html"&gt;Creating IAM Policies - AWS Identity and Access Management&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/security/back-to-school-understanding-the-iam-policy-grammar/"&gt;Back to School: Understanding the IAM Policy Grammar | AWS Security Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>iam</category>
    </item>
    <item>
      <title>Caching in DynamoDB</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Sun, 07 Jun 2020 06:06:21 +0000</pubDate>
      <link>https://dev.to/vinhle95/caching-in-dynamodb-2k27</link>
      <guid>https://dev.to/vinhle95/caching-in-dynamodb-2k27</guid>
      <description>&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%2Fi%2Fs01adhrx61l60xmzz742.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%2Fi%2Fs01adhrx61l60xmzz742.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching
&lt;/h2&gt;

&lt;p&gt;Caching is an essential element in a high-performance database. AWS provide a wide range of &lt;a href="https://aws.amazon.com/caching/aws-caching/" rel="noopener noreferrer"&gt;caching solutions&lt;/a&gt; for its services and environments. For DynamoDB, &lt;a href="https://aws.amazon.com/elasticache/" rel="noopener noreferrer"&gt;ElasticCache&lt;/a&gt; and &lt;a href="https://aws.amazon.com/dynamodb/dax/" rel="noopener noreferrer"&gt;Amazon DynamoDB Accelerator (DAX)&lt;/a&gt; are most preferable choices.&lt;/p&gt;

&lt;p&gt;Both services are in-memory cache in the cloud and designed to offload databases from heavy operations. Front-end clients therefore could retrieve the data faster and improve user experience.&lt;/p&gt;

&lt;p&gt;Despite all these pros, we need to keep in mind that both ElasticCache and DAX are most sensible for READ-intensive applications where clients perform a large amount of GET requests over a period of time. In cases where data is processed in the background and do not need to be retrieved frequently like data warehousing or online transaction applications, ElasticCache and DAX are most likely not a real deal.&lt;/p&gt;

&lt;p&gt;Additionally, ElasticCache can be a layer between clients and various services such as Amazon RDS, S3, and even MongoDB. DAX, on the other hand, is specifically optimized for DynamoDB.&lt;/p&gt;

&lt;p&gt;When server performs a query, it will hit DAX first. DAX then check if it has results of the query in cache. If yes then data will be returned immediately. Otherwise, it will send the query to the database. Here comes to the sweetest part: &lt;em&gt;data will be sync from DynamoDB to DAX&lt;/em&gt;. And even greater, all of these synchronisation and management of DAX is provisioned and carried out by AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caching strategies
&lt;/h2&gt;

&lt;p&gt;There are 2 common types of caching strategies that you could adopt when using caching solutions like ElasticCache: Lazy loading  and Write-through. When to use what really depends upon the data and its access pattern. However, it is important to grasp their difference at first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy loading
&lt;/h3&gt;

&lt;p&gt;This strategy only load data to cache when necessary. It is pretty similar to the way DAX works above. Following diagram might illustrate better.&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%2Fi%2F7cu90970wnim5njp7zt3.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%2Fi%2F7cu90970wnim5njp7zt3.png" alt="Caching strategies"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/Strategies.html" rel="noopener noreferrer"&gt;Source: Caching Strategies - AWS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are 2 cases when server queries database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache Hit: when requested data is already stored in cache. ElasticCache will return the data instantly.&lt;/li&gt;
&lt;li&gt;Cache Miss: this happens with lazy loading in initial requests where the data has not been saved to cache. Query will be sent to database. After that, the server will then update the cache with results that database responded.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Write-through
&lt;/h3&gt;

&lt;p&gt;In this solution, application writes to cache right after it updates the database. This process is repeated in &lt;em&gt;every single request&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros and cons
&lt;/h3&gt;

&lt;p&gt;Both strategies bring nice advantages along with trade-offs in certain aspects.&lt;/p&gt;

&lt;p&gt;For speed and resources, lazy loading is a better way to achieve better performance since the application does not need to update cache every time. The cache also only save &lt;em&gt;meaningful&lt;/em&gt; data that application actually needs and requests. Write-through, on the other hand, tries to update the cache every time. This could certainly result in a longer process.&lt;/p&gt;

&lt;p&gt;However, due to this frequent update, data in cache is never be stale. With lazy loading, cache is not in sync with database. Thus, it could returns to the application with outdated data.&lt;/p&gt;

&lt;p&gt;There is a solution to keep data in cache not too stale by adding time to live to each write to the cache. After the key expires, the cache will treat it as not found and refresh expired key with a fresh value in the database. Keep in mind that there is still a race condition where returned data is still stale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamo TTL - Time to live
&lt;/h2&gt;

&lt;p&gt;Dynamo TTL is an &lt;em&gt;attribute&lt;/em&gt; defines when items in a table will be deleted. To manage TTL, you will need to specify it in &lt;a href="https://en.wikipedia.org/wiki/Unix_time" rel="noopener noreferrer"&gt;Unix time&lt;/a&gt; format for an attribute.&lt;/p&gt;

&lt;p&gt;TTL is very useful to remove data that you no longer need such as user sessions, event logs and temporary data. Process is done automatically in the background and does not affect your table at the mean time.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Caching helps in improving performance for databases of READ-instensive applications.&lt;/li&gt;
&lt;li&gt;To implement caching in DynamoDB, we could use ElasticCache and DAX. ElasticCache could be front door for other database services while DAX is specifically designed for DynamoDB.&lt;/li&gt;
&lt;li&gt;There are 2 types of caching strategies: lazy loading and write-through. Lazy loading only loads to cache data that application asks for while write-through syncs cache with database in every request.&lt;/li&gt;
&lt;li&gt;Time to live (TTL) is an attribute in a DynamoDB table. It decides when to remove unnecessary data in the table. The process is done by DynamoDB in the background.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/Strategies.html" rel="noopener noreferrer"&gt;Caching Strategies - Amazon ElastiCache&lt;/a&gt;&lt;br&gt;
&lt;a href="https://medium.com/fernando-pereiro/caching-strategy-with-dynamodb-streams-aws-lambda-and-elasticache-2b309333cff9" rel="noopener noreferrer"&gt;Caching Strategy with DynamoDB Streams, AWS Lambda and ElastiCache&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aws.amazon.com/blogs/database/amazon-dynamodb-accelerator-dax-a-read-throughwrite-through-cache-for-dynamodb/" rel="noopener noreferrer"&gt;Amazon DynamoDB Accelerator (DAX): A Read-Through/Write-Through Cache for DynamoDB | AWS Database Blog&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>database</category>
      <category>dynamodb</category>
    </item>
    <item>
      <title>Scan and Query in DynamoDB</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Wed, 03 Jun 2020 03:52:03 +0000</pubDate>
      <link>https://dev.to/vinhle95/scan-and-query-in-dynamodb-4c2g</link>
      <guid>https://dev.to/vinhle95/scan-and-query-in-dynamodb-4c2g</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b3e00rAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v2z6qfhqgdjr73s2z1k2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b3e00rAr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/v2z6qfhqgdjr73s2z1k2.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Photo by &lt;a href="https://unsplash.com/@rblvmberg?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Ralph Blvmberg&lt;/a&gt; on &lt;a href="https://unsplash.com"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scan vs. Query
&lt;/h2&gt;

&lt;p&gt;In order to get data from a DynamoDB table, you could either use &lt;em&gt;scan&lt;/em&gt; or &lt;em&gt;query&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query
&lt;/h3&gt;

&lt;p&gt;Query finds items by their &lt;em&gt;primary key&lt;/em&gt; or &lt;em&gt;secondary index&lt;/em&gt;. An item's primary key could be &lt;em&gt;partition key&lt;/em&gt; alone or a combination of &lt;em&gt;partition key&lt;/em&gt; and &lt;em&gt;sort key&lt;/em&gt;. I explained this in greater details in &lt;a href="https://blog.vinhlee.com/dynamo-db-1/"&gt;previous part&lt;/a&gt; of this blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scan
&lt;/h3&gt;

&lt;p&gt;Scan on the other hand return items by going through all items in the table. It first dumps the entire table and then filtering outputs by &lt;em&gt;primary key&lt;/em&gt; or &lt;em&gt;secondary index&lt;/em&gt;, just like query.&lt;/p&gt;

&lt;p&gt;However, scanning process is slower and less efficient than query. It takes an extra step of dumping the whole database and going through &lt;em&gt;all&lt;/em&gt; items.&lt;/p&gt;

&lt;p&gt;We could improve scan performance by &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.Pagination"&gt;pagination&lt;/a&gt; as well as &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html#Scan.ParallelScan"&gt;parallel scan&lt;/a&gt;. Nonetheless, it is still recommended to use query or &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.BatchOperations"&gt;BatchGetItem&lt;/a&gt; over scan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secondary index
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A different data structure
&lt;/h3&gt;

&lt;p&gt;DynamoDB by nature queries and scans by items' primary key. However, it allows more sufficient access to data from other attributes by secondary index. Essentially, you need to specify attributes that could be secondary indexes and run query or scan against them. End of story! 🥂&lt;/p&gt;

&lt;p&gt;It is important to understand that secondary index is a data structure. It is associated with one and only base table where it gets data from.&lt;/p&gt;

&lt;p&gt;This data is primarily a subset of attributes and an alternate key to support query and scan operations. We explicitly define which attributes will be projected (copied) from base table to the index as well as alternate key.&lt;/p&gt;

&lt;p&gt;After an index is created, we could query or scan it similar to a typical table. DynamoDB actively maintains its secondary index. This synchronization happens when we modify (create, remove, update) items in &lt;em&gt;base table&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local vs. Global
&lt;/h3&gt;

&lt;p&gt;There are 2 types of indexes that DynamoDB supports: &lt;strong&gt;local&lt;/strong&gt; and &lt;strong&gt;global&lt;/strong&gt; secondary indexes. Local secondary index has the same partition key and different sort key with its base table while global index has different sort key &lt;em&gt;and&lt;/em&gt; different partition key. That's how &lt;em&gt;local&lt;/em&gt; is different from &lt;em&gt;global&lt;/em&gt; one in a nutshell.&lt;/p&gt;

&lt;p&gt;As global secondary index has different partition key. Its data is stored in a different partition away from the base table while local secondary index shares the same partition with its base. Query in global index therefore could span across partitions, unlike in local one.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use what
&lt;/h3&gt;

&lt;p&gt;Generally, it is &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-indexes-general.html"&gt;recommended&lt;/a&gt; to use global secondary index rather than local one. One exception is when you need &lt;em&gt;strongly consistent read&lt;/em&gt; for your index. Local secondary index supports this consistency model while global one does not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Indexing strategy
&lt;/h3&gt;

&lt;p&gt;Secondary indexes consume storage and provisioned throughput. Thus, a good practice is to keep indexes minimal and could be done by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Project only &lt;em&gt;necessary attributes&lt;/em&gt; that your queries or scans really need&lt;/li&gt;
&lt;li&gt;Attributes that are expected to be frequently fetched should all be secondary indexes to improve performance and save database resources.&lt;/li&gt;
&lt;li&gt;Be aware of &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/LSI.html#LSI.ItemCollections.SizeLimit"&gt;item collection size limit&lt;/a&gt; if you are using local secondary index. In brief, size of all items in base table and its local indexes cannot exceed 10 GB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS also provides a &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-indexes-general.html"&gt;general guideline&lt;/a&gt; that is worth looking into.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;To get data from a DynamoDB table, it is recommended to use query over scan for better performance.&lt;/li&gt;
&lt;li&gt;Secondary index is a data structure. It copies attributes of items from base table and handles queries just like the base table does. Base table keeps secondary index in sync by updating the index when table data changes.&lt;/li&gt;
&lt;li&gt;We could use &lt;em&gt;local&lt;/em&gt; or &lt;em&gt;global secondary index&lt;/em&gt;. The former shares same partition key with base table while the latter has different partition key &lt;em&gt;and&lt;/em&gt; sort key.&lt;/li&gt;
&lt;li&gt;Secondary index consumes database's storage and throughput. Therefore, good practices should be done to archieve better performance while keeping item collection size under limit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-query-scan.html"&gt;Best Practices for Querying and Scanning Data - Amazon DynamoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html"&gt;Improving Data Access with Secondary Indexes - Amazon DynamoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-indexes-general.html"&gt;General Guidelines for Secondary Indexes in DynamoDB - Amazon DynamoDB&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/21381744/difference-between-local-and-global-indexes-in-dynamodb"&gt;indexing - Difference between local and global indexes in DynamoDB - Stack Overflow&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;That's the end of the blog. Thanks for reading 😃💪&lt;br&gt;
The blog is published in my original blog site: &lt;a href="https://blog.vinhlee.com"&gt;https://blog.vinhlee.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>database</category>
      <category>dynamodb</category>
    </item>
    <item>
      <title>DynamoDB 101</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Mon, 01 Jun 2020 04:29:08 +0000</pubDate>
      <link>https://dev.to/vinhle95/dynamodb-101-4m8k</link>
      <guid>https://dev.to/vinhle95/dynamodb-101-4m8k</guid>
      <description>&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%2Fi%2Fblbm9zc1assotmyapy6e.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%2Fi%2Fblbm9zc1assotmyapy6e.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is DynamoDB?
&lt;/h2&gt;

&lt;p&gt;In a nutshell, DynamoDB is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A No-SQL database service provided by Amazon Web Service&lt;/li&gt;
&lt;li&gt;Supports both &lt;a href="https://aws.amazon.com/nosql/key-value/" rel="noopener noreferrer"&gt;key-value&lt;/a&gt; and &lt;a href="https://aws.amazon.com/nosql/document/" rel="noopener noreferrer"&gt;document databases&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Predictable performance by the use of &lt;a href="https://en.wikipedia.org/wiki/Solid-state_drive" rel="noopener noreferrer"&gt;Solid State Disk - SSD&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Multiregion: synchronously data in a DynamoDB table, originally from 1 region, to servers in multiple &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html" rel="noopener noreferrer"&gt;Availability Zones&lt;/a&gt; (AZs)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Consistency model
&lt;/h2&gt;

&lt;p&gt;This starts from data replication support across different AZs. Each AZ connects to another in the same region via low-latency network and sync data.&lt;/p&gt;

&lt;p&gt;Due to this nature, when an application tries to read data from a DynamoDB table, the response might not contain the most up-to-date data. The data will &lt;em&gt;eventually&lt;/em&gt; be consistent across AZs.&lt;/p&gt;

&lt;p&gt;DynamoDB support 2 types of &lt;em&gt;consistency model&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Eventually Consistent Read&lt;/strong&gt;: this model offers ultra-fast response speed. However, you might not get the freshest data up until a short-time-later retry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strongly Consistent Read&lt;/strong&gt;: database always return the most up-to-date data. Nonetheless, this comes with some costs such as higher latency, more resource-intensive as well as potential unavailability due to outages.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building blocks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Tables
&lt;/h3&gt;

&lt;p&gt;DynamoDB stores data in tables. Each table is a collection of data. In MongoDB - another No-SQL database, a table is a &lt;em&gt;collection&lt;/em&gt;. Imagining we have a &lt;em&gt;User&lt;/em&gt; table. We would expect to find any data related to all users in our app. What are inside user table? Well as you might expect, many different users. Each user is an &lt;em&gt;item&lt;/em&gt; of the table.&lt;/p&gt;

&lt;h3&gt;
  
  
  Items
&lt;/h3&gt;

&lt;p&gt;Items are direct child components of Tables. Each item consists of &lt;em&gt;attributes&lt;/em&gt; representing that item. An item in DynamoDB is like a &lt;em&gt;row&lt;/em&gt; or &lt;em&gt;record&lt;/em&gt; in SQL databases (MySQL, PostgreSQL) or a &lt;em&gt;document&lt;/em&gt; in MongoDB.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attributes
&lt;/h3&gt;

&lt;p&gt;An attribute is a primary data element that does not need to be broken down further. A &lt;em&gt;user item&lt;/em&gt;, for instance, has &lt;em&gt;id&lt;/em&gt;, &lt;em&gt;name&lt;/em&gt;, &lt;em&gt;age&lt;/em&gt;, &lt;em&gt;gender&lt;/em&gt;...etc attributes.&lt;/p&gt;

&lt;p&gt;Each item has a unique identifer, or a &lt;em&gt;primary key&lt;/em&gt;, to differentiate itself from other items in the table. Our &lt;em&gt;user&lt;/em&gt; items above could have &lt;em&gt;id&lt;/em&gt; as primary key.&lt;/p&gt;

&lt;p&gt;Most of the attribures have &lt;a href="https://stackoverflow.com/questions/6623130/scalar-vs-primitive-data-type-are-they-the-same-thing" rel="noopener noreferrer"&gt;&lt;em&gt;scalar&lt;/em&gt;&lt;/a&gt; type, which means each attribute is a single value. An attribute could be &lt;em&gt;nested&lt;/em&gt; and contain deeper-level attributes. For example, &lt;em&gt;name&lt;/em&gt; attribute could be an object that has &lt;code&gt;first_name (String)&lt;/code&gt; and &lt;code&gt;last_name (String)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primary keys&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Primary key is a must-known topic of DynamoDB and a distinctive feature compared with other No-SQL alternatives.&lt;/p&gt;

&lt;p&gt;Each &lt;em&gt;item&lt;/em&gt; in a DynamoDB table has a unique &lt;em&gt;primary key&lt;/em&gt;. There are 2 types of supported primary keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partition key&lt;/strong&gt;: unique simple primary key that also involves in &lt;em&gt;where items are saved&lt;/em&gt;. In a nutshell, when DynamoDB saves an item to disk, it hashes that item's partition key. Output of the hash function will determine which partition of the disk the item is going to be stored at.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Partition key and sort key&lt;/strong&gt;: partition key could be non-unique in this case but sort key. We could choose this primary key strategy to store same-partition items together. Let's look at an example:&lt;/li&gt;
&lt;/ul&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%2Fi%2Fg83z1sfgv5f8ebc0oysv.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%2Fi%2Fg83z1sfgv5f8ebc0oysv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Source: &lt;a href="https://aws.amazon.com/blogs/database/choosing-the-right-dynamodb-partition-key/" rel="noopener noreferrer"&gt;Choosing the Right DynamoDB Partition Key&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;We have 2 items with same partition key, which is &lt;code&gt;ProductId&lt;/code&gt; having value of 2. However, their sort keys are different. 1 is &lt;code&gt;AlbumId&lt;/code&gt; and another is &lt;code&gt;AlbumId:TrackId&lt;/code&gt;. This make primary key combination of them different.&lt;/p&gt;

&lt;p&gt;Do keep in mind that sharing a same partition key, however, is not always a good strategy. Frequent access of the same key in a partition can cause request throttling and overload database's provisioned throughput (capacity). Therefore, you should design your tables with the right partition key.&lt;/p&gt;

&lt;p&gt;It is recommended to use &lt;em&gt;high-cardinality&lt;/em&gt; attributes that have unique values for each item such as &lt;code&gt;user_id&lt;/code&gt;, &lt;code&gt;product_id&lt;/code&gt;...Besides, &lt;em&gt;composite&lt;/em&gt; attributes could be a good choice to increase distinctiveness of the values. Take a look at above table example where we have a combination of &lt;code&gt;AlbumID&lt;/code&gt; and &lt;code&gt;TrackID&lt;/code&gt; to be sort key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access control
&lt;/h2&gt;

&lt;p&gt;In order to administer (create, delete) DynamoDB tables, you should have valid IAM credentials and permissions.&lt;/p&gt;

&lt;p&gt;Security-wise, it is recommended to attach a service-specific permission to an user. In this case it could be &lt;code&gt;AmazonDynamoDBFullAccess&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this strategy, each IAM user in your organization only gets access to AWS services that user is allowed to control, instead of a God-mode &lt;code&gt;AdministratorAccess&lt;/code&gt;. I will have a separate post on IAM roles in AWS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read/Write capacity mode
&lt;/h2&gt;

&lt;p&gt;When creating a new DynamoDB table, we need to configure its capacity to read and write data. This is quite app-specific and DynamoDB supports 2 capacity modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;On-demand&lt;/strong&gt;: a tailored feature for &lt;em&gt;unpredictable&lt;/em&gt; workloads and traffics. This mode offers pay-per-request pricing so you only pay for what you actually used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provisioned mode&lt;/strong&gt;: fit for applications that have &lt;em&gt;predictable&lt;/em&gt; and &lt;em&gt;consistent&lt;/em&gt; traffics. In this mode, you need to specify database throughput in &lt;em&gt;read capacity units&lt;/em&gt; (RCUs) and &lt;em&gt;write capacity units&lt;/em&gt; (WCUs).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How could you calculate RCUs and WCUs of your table? Here are factors that you should know in advance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many &lt;em&gt;items&lt;/em&gt; the table is expected to read/write &lt;em&gt;per second&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Size of each item (KB)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take an example when our table needs capacity to read 80 items per second. Each item has size of 3 KB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calculating read capacity units (RCUs)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1 RCU represents 1 &lt;em&gt;strongly consistent read&lt;/em&gt; or 2 &lt;em&gt;eventually consistent read&lt;/em&gt; per second, for an item up to 4 KB in size&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, if our table uses &lt;em&gt;eventually consistent read&lt;/em&gt;, we would need: &lt;code&gt;Math.ceil(3/4) = 1&lt;/code&gt; RCU. Therefore, we need to specify &lt;code&gt;1 x 80 = 80&lt;/code&gt; RCUs for our table so that it could read 80 items per second.&lt;/p&gt;

&lt;p&gt;With &lt;em&gt;strongly consistent read&lt;/em&gt;, the number would be &lt;code&gt;80/2 = 40&lt;/code&gt; RCUs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Calculating write capacity units (WCUs)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;1 WCU represent 1 &lt;em&gt;write per second&lt;/em&gt; for an item up to 1 KB in size&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So because each item's size is 3 KB, in order to write an item to the table, we need &lt;code&gt;3/1 = 3&lt;/code&gt; WCUs.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;DynamoDB is a predictable performance, No-SQL Amazon's database service.&lt;/li&gt;
&lt;li&gt;It supports key-value and document databases. It is also multiregional, which means your data is synchronised across multiple Availability Zones.&lt;/li&gt;
&lt;li&gt;DynamoDB supports 2 types of consistency model: &lt;em&gt;eventually consistent read&lt;/em&gt; and &lt;em&gt;strongly consistent read&lt;/em&gt;. The former offers high speed responses while the latter guarantees the most up-to-date data.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Tables, Items, Attributes&lt;/em&gt; are core components of DynamoDB. Each item in a table must have unique &lt;em&gt;primary key&lt;/em&gt;. It could be a distinct &lt;em&gt;partition key&lt;/em&gt; alone or a combination of non-unique &lt;em&gt;partition key&lt;/em&gt; and a unique &lt;em&gt;sort key&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;In order to administer DynamoDB tables, an IAM user with valid permissions is required.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;On-demand&lt;/em&gt; and &lt;em&gt;Provisioned&lt;/em&gt; are 2 &lt;em&gt;capacity mode&lt;/em&gt; that we need to specify when creating a new table. &lt;em&gt;On-demand&lt;/em&gt; mode is ideal for unpredictable workload applications. &lt;em&gt;Provisioned&lt;/em&gt; mode requires us to specify the table's capacity in &lt;em&gt;read capacity units&lt;/em&gt; and &lt;em&gt;write capacity units&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>database</category>
      <category>aws</category>
      <category>dynamodb</category>
      <category>nosql</category>
    </item>
    <item>
      <title>Tooling for boosting your development workflow</title>
      <dc:creator>Vinh Le</dc:creator>
      <pubDate>Sun, 25 Aug 2019 14:26:41 +0000</pubDate>
      <link>https://dev.to/vinhle95/tooling-for-boosting-your-development-workflow-1dgg</link>
      <guid>https://dev.to/vinhle95/tooling-for-boosting-your-development-workflow-1dgg</guid>
      <description>&lt;h2&gt;
  
  
  Part 1: Code formatting
&lt;/h2&gt;

&lt;p&gt;If programming is just a 1-person-to-computer process, things will probably be dead simple. You write whatever you think that will work, and the computer will help you to verify.&lt;/p&gt;

&lt;p&gt;Sadly, that is not how it works most of the time. When you work in a team, your peers will need to review your codes and vice versa. Here is the time where things heat up &lt;em&gt;a little bit&lt;/em&gt; 🙃&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%2Fi.imgflip.com%2F38s5zo.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%2Fi.imgflip.com%2F38s5zo.jpg" title="why formatting" alt="code formatting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why bothering?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Poorly formatted codes slow down review process
&lt;/h3&gt;

&lt;p&gt;When coworkers tag you in a pull request (PR), they want to quickly get approval to move the next feature out of backlog. On the other side, you want to go through it fast as well. However, when the code is poorly formatted, or even worse, not formatted at all, you both are in trouble.&lt;/p&gt;

&lt;p&gt;Let's face the truth: each of us has different &lt;em&gt;coding style&lt;/em&gt;. Thus, this difference will surely take you more time to understand logics underneath.&lt;/p&gt;

&lt;p&gt;Take an example of handling a &lt;strong&gt;Promise&lt;/strong&gt; in JavaScript in general:&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="nf"&gt;getShots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myShotsEndpoint&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shots&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;shots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shot&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;saveMyShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;removeMyLastShot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;})}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nf"&gt;getErrorStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;handleUnauthenticatedUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;showErrorMessage&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 my shot now!!!&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;Urghhhh 🤦🏻‍♂️😐🔥&lt;/p&gt;

&lt;p&gt;I know what you are having in mind 😤But bear with me a little more. If you get into Space/Tab trouble, no don't lie, I know you were 🤗 functions like this will probably ruin your day:&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="nf"&gt;getShots&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;myShotsEndpoint&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;shots&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;shots&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shot&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;saveMyShot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shot&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;removeMyLastShot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;})}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nf"&gt;getErrorStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;handleUnauthenticatedUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nf"&gt;showErrorMessage&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 my shot now!!!&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;blockquote&gt;
&lt;p&gt;I understand, it is exhausting reading those codes 😥&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And this is just a Promise handler. Imagining there are tens of components with function logics, UI elements, styling..etc ahead. Your job is to &lt;em&gt;go through all of them&lt;/em&gt;. Annoyingly, this blocker significantly slows you down.&lt;/p&gt;

&lt;p&gt;And trust me, your colleague is not happy either when getting a comment like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Please add 1 more tab in line number 531"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Their jobs are to take care of business logics, not a small space/tab that you, the reviewer, does not feel right. From here, you have no choice rather than giving up, accepting a painful truth and telling yourself&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;There will be no problem. The computer will take care of that.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Until a day...&lt;/p&gt;

&lt;h3&gt;
  
  
  A nightmare to maintain
&lt;/h3&gt;

&lt;p&gt;A new guy comes in to maintain this project and his reaction will probably follow this chain: 🧐🤨😡🤬&lt;/p&gt;

&lt;p&gt;These uggggly code blocks will surely make it more difficult to maintain. When more developers go on board with different coding styles, maintainance becomes more challenging.&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%2Fi.imgflip.com%2F38s842.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%2Fi.imgflip.com%2F38s842.jpg" title="rewrite" alt="rewrite"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fortunately, you don't.
&lt;/h3&gt;

&lt;p&gt;There are tools out there that could be your team's saviour. Let me introduce 1 of them that already saved mine 🤩&lt;/p&gt;

&lt;h2&gt;
  
  
  Prettier
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://prettier.io/" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; is an awesome tool for code formatting. It has supports for many languages, great documentation and easy to get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Time for coding now! 👨🏻‍💻💪
&lt;/h3&gt;

&lt;p&gt;I will show you how to set it up in a NodeJS module, as it is what I feel most comfortable with 🔥&lt;br&gt;
Nonetheless, it should share many similarities with your projects.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: Install &lt;a href="https://www.npmjs.com/package/prettier" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/tslint" rel="noopener noreferrer"&gt;TSLint&lt;/a&gt; (or ESLint if you are not a fan of TypeScript)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; prettier tslint
&lt;span class="nt"&gt;--or--&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; prettier tslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You also need to install some helpers/plugins to make Prettier and TS Lint works nicely together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; tslint-config-prettier tslint-plugin-prettier
&lt;span class="nt"&gt;--or--&lt;/span&gt;
yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; tslint-config-prettier tslint-plugin-prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a nutshell, &lt;a href="https://github.com/prettier/tslint-config-prettier" rel="noopener noreferrer"&gt;&lt;code&gt;tslint-config-prettier&lt;/code&gt;&lt;/a&gt; disables &lt;a href="https://unpkg.com/tslint-config-prettier@1.18.0/lib/index.json" rel="noopener noreferrer"&gt;conflicting rules&lt;/a&gt; between TSLint and Prettier.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Config linting rules for TSLint
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;tslint.json&lt;/code&gt; file in the root directory of the project:&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;touch &lt;/span&gt;tslint.json
code &lt;span class="nb"&gt;.&lt;/span&gt; tslint.json &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(*) The command &lt;code&gt;code .&lt;/code&gt; I used is a feature of &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt;. Hands up VSCode fans! 🚀&lt;/p&gt;

&lt;p&gt;You then can add rules in this config file. For the sake of simplicity, I will introduce some basic rules. Go &lt;a href="https://github.com/palantir/tslint" rel="noopener noreferrer"&gt;here&lt;/a&gt; for your specific needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;tslint.json&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;defaultSeverity&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="s2"&gt;error&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="s2"&gt;extends&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tslint:recommended&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="s2"&gt;tslint-config-prettier&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="s2"&gt;jsRules&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rulesDirectory&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tslint-plugin-prettier&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="s2"&gt;rules&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prettier&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;linterOptions&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exclude&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node_modules/**/*.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;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Add prettier (formatting) rules
&lt;/h3&gt;

&lt;p&gt;You will need to tell Prettier how you want your code to be formatted. To do that, let's create a &lt;a href="https://prettier.io/docs/en/configuration.html" rel="noopener noreferrer"&gt;config file&lt;/a&gt;, just like what we did for TSLint&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;touch&lt;/span&gt; .prettierrc
code &lt;span class="nb"&gt;.&lt;/span&gt; .prettierrc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's add some rules in this file ✍️&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "arrowParens": "avoid",
    "bracketSpacing": false,
    "insertPragma": false,
    "printWidth": 80,
    "proseWrap": "preserve",
    "requirePragma": false,
    "semi": false,
    "singleQuote": true,
    "trailingComma": "all",
    "tabWidth": 2,
    "useTabs": true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember, what you specify here will be exactly how Prettier formats your code. For example, last 2 lines tell Prettier to use Tab width = 2 (Sorry Space fans out there 😔). &lt;code&gt;"singleQuote": true&lt;/code&gt;, for instance, will replace all double quotes by single ones. There are many other &lt;a href="https://prettier.io/docs/en/options.html" rel="noopener noreferrer"&gt;options&lt;/a&gt; which you might want to refer to.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Format your code
&lt;/h3&gt;

&lt;p&gt;There are 2 ways that you can do it, either right before saving a file or all files together when you feel like.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Format on Save&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is an Editor-specific feature, which means you have to enable this feature inside your editor's Settings. In &lt;a href="https://code.visualstudio.com/docs/getstarted/settings" rel="noopener noreferrer"&gt;VSCode&lt;/a&gt;, for instance, you can do that by putting this line in &lt;code&gt;settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"editor.formatOnSave": true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Format the entire project&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I personally prefer this way as it gives me more control over which types of file that I want to format. Let's write a script in &lt;code&gt;package.json&lt;/code&gt;&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="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"awesome-formatter"&lt;/span&gt;&lt;span class="err"&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;"ShotCode &amp;lt;shotcode@gmail.com&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"format"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;**/*.+(js|json|ts|md|mdx|graphql)&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; --write"&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;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does that &lt;code&gt;format&lt;/code&gt; script do?&lt;/p&gt;

&lt;p&gt;It tells Prettier to apply formatting rules that we configured in &lt;code&gt;prettierrc&lt;/code&gt; on specified file extensions. In this case, they are &lt;code&gt;.js, .json, .ts...&lt;/code&gt; you name it. Next we tell Prettier to &lt;strong&gt;override&lt;/strong&gt; those files by &lt;code&gt;--write&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Let's run the script and see how it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run format
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgflip.com%2F38uiaa.gif" 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%2Fi.imgflip.com%2F38uiaa.gif" title="format script" alt="format script"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Boom! It is so cool isn't it? 🤩🏎&lt;/p&gt;

&lt;p&gt;To bring this to the next level, you can configure this script to run with Git hooks. So that your code will be nicely formatted before committing, for instance. If you are curious about it, stay tuned for the next part 🥳&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Poorly formatted code sucks. Period.&lt;/li&gt;
&lt;li&gt;Why? It takes much longer time to review, harder to maintain, especially in a large project with dozens of developers.&lt;/li&gt;
&lt;li&gt;How to format your code properly? Get used of awesome tools like &lt;strong&gt;Prettier&lt;/strong&gt;. It is easy to set up, pleasing to see the result and works nicely with other processes in your workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  But wait, you are not the only decision maker 😔
&lt;/h2&gt;

&lt;p&gt;If your peers are hesitating about using Prettier, I belive that its great features and benefits are weighty reasons for at least giving a try. And trust me, you all are gonna love it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You don't have to worried about your peers' coding style anymore. Let's just keep writing something awesome. And let the computer handle the rest.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Thanks for reading this blog!
&lt;/h2&gt;

&lt;p&gt;I would love to hear your thoughts in the comment section bellow 🤗&lt;/p&gt;

&lt;h2&gt;
  
  
  And stay tuned for upcoming ones 🤩
&lt;/h2&gt;




&lt;h3&gt;
  
  
  ✍️ Written by
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Vinh Le&lt;/strong&gt; &lt;a href="https://twitter.com/vinhle95" rel="noopener noreferrer"&gt;@vinhle95&lt;/a&gt; 👨🏻‍💻🤓🏋️‍🏸🎾♂️🚀&lt;/p&gt;

&lt;p&gt;A hustler, lifelong learner, tech lover &amp;amp; software developer&lt;/p&gt;

&lt;p&gt;Say Hello 👋 on&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/vinhlee95" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://www.linkedin.com/in/vinhlee95/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://medium.com/@vinhle95" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://vinhlee.com/" rel="noopener noreferrer"&gt;Personal site&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tooling</category>
      <category>prettier</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
