<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Blog</title>
    <link>https://www.craftsmensoftware.com/blog</link>
    <description>Empower your business with our expert team augmentation services. Scale efficiently and stay ahead in the ever-evolving tech landscape.</description>
    <language>en</language>
    <pubDate>Thu, 30 Apr 2026 08:22:25 GMT</pubDate>
    <dc:date>2026-04-30T08:22:25Z</dc:date>
    <dc:language>en</dc:language>
    <item>
      <title>Publishing a React website on AWS with AWS amplify and AWS CloudFront with Custom Domain (Part 2) - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/publishing-a-react-website-on-aws-with-aws-amplify-and-aws-cloudfront-with-custom-domain-part-2</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/publishing-a-react-website-on-aws-with-aws-amplify-and-aws-cloudfront-with-custom-domain-part-2" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/Publishing-a-React-website-on-AWS-with-AWS-amplify-Part-2.webp" alt="Publishing a React website on AWS with AWS amplify and AWS CloudFront with Custom Domain (Part 2) - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-4563"&gt; 
  &lt;div class="elementor-element elementor-element-7f304019 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-10ef37ab elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container" style="font-size: 16px;"&gt; 
      &lt;p&gt;This post is a part of the series which will help you publish your React based project/website on AWS using AWS Amplify and AWS CloudFront. This part will walk you through the steps to setup AWS CloudFront so that you can access your website using any domain of your own.&lt;br&gt;&lt;br&gt;If you want to learn about how to upload your React project on AWS using AWS Amplify or if you just want to follow along with this whole series, check out&amp;nbsp;&lt;a href="http://bit.ly/3rtpKqi"&gt;&lt;strong&gt;&lt;em&gt;Part 1&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. This post will continue from where we left off in the first part. So it’s recommended that you go through that one first.&lt;/p&gt; 
      &lt;p&gt;Part 1 covers the React project creation and AWS Amplify part.&lt;br&gt;Part 2 covers the CloudFront configuration and custom domain setup part.&lt;/p&gt; 
      &lt;h2 class="wp-block-heading"&gt;Before You Begin (part 2)&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;As this post uses AWS, we will assume that you already have an AWS account or have access to an account, as you will need to use your credentials for AWS Amplify and will need to go to AWS console and configure AWS CloudFront. If you still think this post can help you, then let’s get into it.&lt;/p&gt; 
      &lt;h2 class="wp-block-heading"&gt;Create an AWS CloudFront Distribution&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;Well, to begin with, what we need to do first? Of course create a new CloudFront distribution, what else, right? So let’s head to the &lt;a href="https://console.aws.amazon.com/cloudfront/home"&gt;AWS CloudFront console home page&lt;/a&gt;&amp;nbsp;and select the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Create Distribution&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;button.&lt;/p&gt;   CloudFront Home page   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;After that, it will take you to the delivery method selection page, where, as of the time of this post writing, you will be given two(2) options to choose from, one is&amp;nbsp;&lt;strong&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/strong&gt;, the other one is&amp;nbsp;&lt;strong&gt;&lt;em&gt;RTMP&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;(which will be discontinued from&lt;strong&gt;&amp;nbsp;December 31, 2020&lt;/strong&gt;). We will be selecting the&amp;nbsp;&lt;strong&gt;Web&amp;nbsp;&lt;/strong&gt;one.&lt;/span&gt;&lt;/p&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now we will actually get the main form to create a new CloudFront Distribution.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;If you click on the&amp;nbsp;&lt;em&gt;Origin Domain Name&amp;nbsp;&lt;/em&gt;input box, AWS will suggest the S3 buckets you have along with some other options. We need to select the one we created in&amp;nbsp;&lt;a href="http://bit.ly/3rtpKqi"&gt;&lt;strong&gt;&lt;em&gt;Part 1&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;,&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;which was&amp;nbsp;&lt;em&gt;reactawsamplify-20201222013512-hostingbucket-dev.&amp;nbsp;&lt;/em&gt;But there is a catch, we can’t just select the bucket from the drop-down as it will only point the distribution to the bucket, which we don’t want. We want the distribution to point at the hosting site. So instead of just writing the name of the bucket, we will write the entire hosting URL.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;By this time, you might be wondering how the hell you will get the URL? Do you have to publish the project with AWS Amplify again just to get the URL? Well, don’t worry about that, you don’t have to go to such length. There is an easy and convenient way to get that. Just go into the S3 bucket, and select the &lt;em&gt;Properties&lt;/em&gt;&amp;nbsp;tab on the top.&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;Select the&amp;nbsp; &lt;strong&gt;Properties&lt;/strong&gt;&amp;nbsp;tab on the S3 bucket&lt;/span&gt;   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;On that page, went to the bottom of the page and you will find a card named&amp;nbsp;&lt;strong&gt;&lt;em&gt;Static website hosting&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;and there you will find the desired URL.&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;The URL of the hosting site&lt;/span&gt;   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Copy that URL and paste it on the CloudFront Distribution page’s&amp;nbsp;&lt;strong&gt;Origin Domain Name&amp;nbsp;&lt;/strong&gt;input field and click anywhere outside. It will load the necessary information into the other input fields.&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;Paste the URL in this input box&lt;/span&gt;   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now let’s set up the other fields that we need. We will keep the default value for the following fields:&amp;nbsp;&lt;strong&gt;Enable Origin Shield, Origin Connection Attempts, Origin Connection Timeout, Smooth Streaming, Restrict Viewer Access(Use Signed URLs or Signed Cookies), Compress Objects Automatically, Supported HTTP Versions, Enable IPv6.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;So let’s start customizing the&amp;nbsp;&lt;strong&gt;Default Cache Behavior Settings&lt;/strong&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class="wp-block-list"&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;1st of all, we will change the&amp;nbsp;&lt;strong&gt;Viewer Protocol Policy&amp;nbsp;&lt;/strong&gt;settings. You can keep it as it is, but it’s recommended to change it to&amp;nbsp;&lt;em&gt;Redirect HTTP to HTTPS.&lt;/em&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;2nd, as our current website doesn’t have any PUT, POST, or DELETE operations, we will not change&amp;nbsp;&lt;strong&gt;Allowed HTTP Methods.&amp;nbsp;&lt;/strong&gt;But if you have a form or you communicate with an API, then you need to select the&amp;nbsp;&lt;em&gt;GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE&amp;nbsp;&lt;/em&gt;option.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;3rd, for the&amp;nbsp;&lt;strong&gt;Cache and origin request settings,&amp;nbsp;&lt;/strong&gt;we’ll change it to&amp;nbsp;&lt;em&gt;Use legacy cache settings&amp;nbsp;&lt;/em&gt;as we don’t want to keep any cache. If you want to keep it, don’t change the settings.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;If in the 3rd one, you selected the&amp;nbsp;&lt;em&gt;Use legacy cache settings,&amp;nbsp;&lt;/em&gt;then you will get an&amp;nbsp;&lt;strong&gt;Object Caching&amp;nbsp;&lt;/strong&gt;option. Which we will change to&amp;nbsp;&lt;em&gt;Customize&amp;nbsp;&lt;/em&gt;and then set the&amp;nbsp;&lt;strong&gt;Minimum TTL, Maximum TTL, Default TTL&amp;nbsp;&lt;/strong&gt;to 0 (zero). This will help the users to get up-to-date content each time they reload the page.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;This is the end result so far that we have implemented in the distribution page:&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;The settings we implemented so far in the previous steps&lt;/span&gt;   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now it’s time for the&amp;nbsp;&lt;strong&gt;Distribution Settings&lt;/strong&gt;&amp;nbsp;part. In this part, we will actually keep most of the things as it is, but this is the place where we will set up the custom domain. You can do that later so we will go through the process for now and keep all the default values. Just click&amp;nbsp;&lt;strong&gt;Create Distribution&lt;/strong&gt;&amp;nbsp;at the bottom and you are done!!&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;You will be taken to the CloudFront home page and you will find the distribution you just created.&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;You will find the distribution on the CloudFront home page&lt;/span&gt;   
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;It takes some time for the distribution to be deployed for the first time. When it’s done, you will the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Status&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;as&amp;nbsp;&lt;strong&gt;Deployed&lt;/strong&gt;. When that is ready, you can copy the&amp;nbsp;&lt;strong&gt;Domain Name&amp;nbsp;&lt;/strong&gt;and paste it in the browser and you will see it’s showing the website you hosted on the S3 bucket! So now you don’t have to remember the long S3 bucket hosting URL just to visit the website.&lt;/span&gt;&lt;/p&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;Use the URL from the domain name to visit the website.&lt;/span&gt;    
      &lt;span style="font-size: 16px;"&gt;&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;Website loading using the Domain name from the CloudFront&lt;/span&gt;   
      &lt;h2 class="wp-block-heading"&gt;Setting up Custom Domain&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;For setting the custom domain, we need two things.&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;A registered domain and access to that domain’s DNS setting or access to the mails for that domain.&lt;/li&gt; 
       &lt;li&gt;A custom SSL certificate generated from AWS&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;We’ll assume you already have a domain registered somewhere. And you have access to your&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;DNS settings&lt;/a&gt;. But if you don’t have access to&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;DNS&lt;/a&gt;, then it’s alright too, as we will show you how to get registered using email as well.&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;To get the SSL Certificate, if you already don’t have one, you can just click the&amp;nbsp;&lt;strong&gt;Request or Import a Certificate with ACM&amp;nbsp;&lt;/strong&gt;from the distribution page.&lt;/p&gt;  Or you can also directly to the&amp;nbsp; 
      &lt;a href="https://console.aws.amazon.com/acm/home?region=us-east-1#/wizard/"&gt;&lt;strong&gt;Request Certificate&lt;/strong&gt;&lt;/a&gt;page.    Request custom SSL Certificate page   
      &lt;p style="font-size: 16px;"&gt;Enter your custom domain name and press&amp;nbsp;&lt;strong&gt;Next.&lt;/strong&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;Then you will be taken to the&amp;nbsp;&lt;strong&gt;Select validation method&amp;nbsp;&lt;/strong&gt;page, where you will get two types of validation method:&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;DNS validation:&amp;nbsp;&lt;/strong&gt;It’s the most used one. It requires the user to go to the&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;domain DNS settings&lt;/a&gt;&amp;nbsp;page, then adding a new&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/CNAME_record"&gt;&lt;strong&gt;CNAME&lt;/strong&gt;&amp;nbsp;record&lt;/a&gt;.&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Email validation:&amp;nbsp;&lt;/strong&gt;It uses some pre-configured email address to send you a validation email where you will be asked to verify that you requested the SSL certificate. If you accept that, then it will create an ACM SSL certificate in AWS. The email addresses are:&lt;br&gt;* postmaster@yourdomain.com&lt;br&gt;* hostmaster@yourdomain.com&lt;br&gt;* admin@yourdomain.com&lt;br&gt;* webmaster@yourdomain.com&lt;br&gt;* administrator@yourdomain.com&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;We will just briefly walk you through both of the ways just in a bit. But for now, let’s continue by selecting the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Email validation&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;option as it is the easy one.&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;In the next step, just press&amp;nbsp;&lt;strong&gt;Review&lt;/strong&gt;&amp;nbsp;and you will be given a final checkup.&lt;/p&gt;   Make sure everything is in place   
      &lt;p style="font-size: 16px;"&gt;Now hit&amp;nbsp;&lt;strong&gt;Confirm&lt;/strong&gt;&amp;nbsp;and it’s ready to go. AWS will send you an email for the confirmation on the pre-configured email addresses as mentioned before.&lt;/p&gt;  
      &lt;span style="background-color: transparent;"&gt;Email is sent to the shown email addresses&lt;/span&gt;  
      &lt;p style="font-size: 16px;"&gt;Until you verify your email or set up the DNS, you will see the verification status as&amp;nbsp;&lt;em&gt;Pending validation&lt;/em&gt;.&lt;/p&gt;   Waiting for confirmation   
      &lt;p style="font-size: 16px;"&gt;This is how a verification email looks like:&lt;/p&gt;   The verification email from AWS   
      &lt;p style="font-size: 16px;"&gt;Just press the&amp;nbsp;&lt;strong&gt;Amazon Certificate Approvals&amp;nbsp;&lt;/strong&gt;link or copy and paste the URL on any browser and it will show you the message again. Hit the&amp;nbsp;&lt;strong&gt;I Approve&lt;/strong&gt;&amp;nbsp;button and you are all set!&lt;br&gt;&lt;br&gt;You can find that on the SSL certificate page as well if you refresh it.&lt;/p&gt;   
      &lt;strong&gt;The domain SSL certificate is created&lt;/strong&gt; 
      &lt;br&gt; 
      &lt;span style="background-color: transparent;"&gt;For some domain/hosting platform, the Email Validation doesn’t work. If you find that the domain is not working, try using the DNS Validation instead of Email Validation. The DNS CNAME record-setting differs for different vendors. So we can’t cover that here.&lt;/span&gt;   
      &lt;p style="font-size: 16px;"&gt;&lt;strong&gt;DNS validation Process&lt;br&gt;&lt;/strong&gt;In case you selected DNS instead of Email, you will have to follow a different route. In that case, after you&amp;nbsp;&lt;strong&gt;Confirm&amp;nbsp;&lt;/strong&gt;the process, you will get this:&lt;/p&gt;  
      &lt;strong style="background-color: transparent;"&gt;CNAME record credentials&lt;/strong&gt;  
      &lt;strong&gt;&amp;nbsp;&lt;/strong&gt;  You will find the credentials you need to set in the domain DNS system as a CNAME record. You can also download that credentials CSV file if you want to do it later or send it to someone who has access to the DNS settings. After the CNAME record is created, it will show the status as&amp;nbsp; 
      &lt;strong&gt;&lt;em&gt;issued&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;in the SSL certificate list.  
      &lt;p style="font-size: 16px;"&gt;When setting up the CNAME, you actually will need to set up 2 CNAME records.&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;For verifying the custom SSL certificate. In this case, the name and value you will get from the AWS, the image we’ve shown just before.&lt;/li&gt; 
       &lt;li&gt;For redirecting to the CloudFront when we enter the domain on a browser. The name for this one will be the&amp;nbsp;&lt;em&gt;custom domain name&lt;/em&gt;&amp;nbsp;you want to set up for the website (in our case&amp;nbsp;&lt;em&gt;reactaws.apphousebd.com&lt;/em&gt;) and the value will be the CloudFront distribution domain name. Keep in mind the&amp;nbsp;&lt;em&gt;custom domain name&amp;nbsp;&lt;/em&gt;you set up for as the name, because it will be needed later when setting up the&amp;nbsp;&lt;strong&gt;Alternate Domain Names (CNAMEs)&amp;nbsp;&lt;/strong&gt;field.&lt;/li&gt; 
      &lt;/ol&gt;   
      &lt;strong&gt;CloudFront distribution domain name&lt;br&gt;&lt;/strong&gt;  It may take some time to verify the domain with DNS validation, so wait at least 5–10 mins before trying again.  
      &lt;h2 class="wp-block-heading"&gt;Setting the Custom domain in CloudFront&lt;/h2&gt; 
      &lt;p&gt;Now for the moment that we are building up the whole thing!&lt;/p&gt; 
      &lt;p&gt;Go to the CloudFront distribution page and select&amp;nbsp;&lt;em&gt;Edit&lt;/em&gt;.&lt;/p&gt;  
      &lt;ul class="wp-block-list"&gt; 
       &lt;li&gt;There in the&amp;nbsp;&lt;strong&gt;Alternate Domain Names (CNAMEs)&amp;nbsp;&lt;/strong&gt;field, enter the custom domain name of which you have already created an SSL certificate.&lt;/li&gt; 
       &lt;li&gt;After that, select the&amp;nbsp;&lt;em&gt;Custom SSL Certificate (example.com)&amp;nbsp;&lt;/em&gt;option for&amp;nbsp;&lt;strong&gt;SSL Certificate.&amp;nbsp;&lt;/strong&gt;There if you click on the input box, you will find the SSL certificate you created. Select the one with the domain you entered in the previous step.&lt;/li&gt; 
       &lt;li&gt;Enter&amp;nbsp;&lt;em&gt;index.html&lt;/em&gt;&amp;nbsp;in the&amp;nbsp;&lt;strong&gt;Default Root Object&amp;nbsp;&lt;/strong&gt;input field&lt;/li&gt; 
       &lt;li&gt;Keep the other thins as it is.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt;   Distribution setting after everything is set up   
      &lt;p&gt;Hit&amp;nbsp;&lt;strong&gt;Yes, Edit&lt;/strong&gt;&amp;nbsp;and that’s it. Finally, everything is over!!! Just wait until the status of the CloudFront distribution is changed from&amp;nbsp;&lt;strong&gt;In Progress&lt;/strong&gt;&amp;nbsp;to&amp;nbsp;&lt;strong&gt;Deployed&amp;nbsp;&lt;/strong&gt;and then you can test the website with the custom domain you just set.&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;Well, it’s been a long way since the start. But I believe you now have enough knowledge about how to deploy your own or any other person’s React website on AWS. Hope this post helps you in your exciting coding/developer life.&lt;/p&gt; 
      &lt;p&gt;Happy coding!&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-4563"&gt; 
  &lt;div class="elementor-element elementor-element-7f304019 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-10ef37ab elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container" style="font-size: 16px;"&gt; 
      &lt;p&gt;This post is a part of the series which will help you publish your React based project/website on AWS using AWS Amplify and AWS CloudFront. This part will walk you through the steps to setup AWS CloudFront so that you can access your website using any domain of your own.&lt;br&gt;&lt;br&gt;If you want to learn about how to upload your React project on AWS using AWS Amplify or if you just want to follow along with this whole series, check out&amp;nbsp;&lt;a href="http://bit.ly/3rtpKqi"&gt;&lt;strong&gt;&lt;em&gt;Part 1&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. This post will continue from where we left off in the first part. So it’s recommended that you go through that one first.&lt;/p&gt; 
      &lt;p&gt;&lt;span style="background-color: transparent;"&gt;&lt;/span&gt;Part 1 covers the React project creation and AWS Amplify part.&lt;br&gt;Part 2 covers the CloudFront configuration and custom domain setup part.&lt;/p&gt; 
      &lt;h2 class="wp-block-heading"&gt;Before You Begin (part 2)&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;As this post uses AWS, we will assume that you already have an AWS account or have access to an account, as you will need to use your credentials for AWS Amplify and will need to go to AWS console and configure AWS CloudFront. If you still think this post can help you, then let’s get into it.&lt;/p&gt; 
      &lt;h2 class="wp-block-heading"&gt;Create an AWS CloudFront Distribution&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;Well, to begin with, what we need to do first? Of course create a new CloudFront distribution, what else, right? So let’s head to the &lt;a href="https://console.aws.amazon.com/cloudfront/home"&gt;AWS CloudFront console home page&lt;/a&gt;&amp;nbsp;and select the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Create Distribution&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;button.&lt;/p&gt; 
      &lt;img width="1024" height="143" class="wp-image-4564" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_Ay1VoTGcUyoJQHTAl8QFkA.webp?width=1024&amp;amp;height=143&amp;amp;name=1_Ay1VoTGcUyoJQHTAl8QFkA.webp" alt=""&gt; CloudFront Home page  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;After that, it will take you to the delivery method selection page, where, as of the time of this post writing, you will be given two(2) options to choose from, one is&amp;nbsp;&lt;strong&gt;&lt;em&gt;Web&lt;/em&gt;&lt;/strong&gt;, the other one is&amp;nbsp;&lt;strong&gt;&lt;em&gt;RTMP&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;(which will be discontinued from&lt;strong&gt;&amp;nbsp;December 31, 2020&lt;/strong&gt;). We will be selecting the&amp;nbsp;&lt;strong&gt;Web&amp;nbsp;&lt;/strong&gt;one.&lt;/span&gt;&lt;/p&gt; 
      &lt;img width="700" height="244" class="wp-image-4568" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_JNGMkmcnR3N204ECHTbhjg.webp?width=700&amp;amp;height=244&amp;amp;name=1_JNGMkmcnR3N204ECHTbhjg.webp" alt=""&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now we will actually get the main form to create a new CloudFront Distribution.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;If you click on the&amp;nbsp;&lt;em&gt;Origin Domain Name&amp;nbsp;&lt;/em&gt;input box, AWS will suggest the S3 buckets you have along with some other options. We need to select the one we created in&amp;nbsp;&lt;a href="http://bit.ly/3rtpKqi"&gt;&lt;strong&gt;&lt;em&gt;Part 1&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;em&gt;,&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;which was&amp;nbsp;&lt;em&gt;reactawsamplify-20201222013512-hostingbucket-dev.&amp;nbsp;&lt;/em&gt;But there is a catch, we can’t just select the bucket from the drop-down as it will only point the distribution to the bucket, which we don’t want. We want the distribution to point at the hosting site. So instead of just writing the name of the bucket, we will write the entire hosting URL.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;By this time, you might be wondering how the hell you will get the URL? Do you have to publish the project with AWS Amplify again just to get the URL? Well, don’t worry about that, you don’t have to go to such length. There is an easy and convenient way to get that. Just go into the S3 bucket, and select the &lt;em&gt;Properties&lt;/em&gt;&amp;nbsp;tab on the top.&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="299" class="wp-image-4569" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_ovaOR-ou3yNfng3PbcvyKQ.webp?width=700&amp;amp;height=299&amp;amp;name=1_ovaOR-ou3yNfng3PbcvyKQ.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;Select the&amp;nbsp; &lt;strong&gt;Properties&lt;/strong&gt;&amp;nbsp;tab on the S3 bucket&lt;/span&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;On that page, went to the bottom of the page and you will find a card named&amp;nbsp;&lt;strong&gt;&lt;em&gt;Static website hosting&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;and there you will find the desired URL.&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="156" class="wp-image-4570" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_PFgqCulywltUBvNZlD25lg.webp?width=700&amp;amp;height=156&amp;amp;name=1_PFgqCulywltUBvNZlD25lg.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;The URL of the hosting site&lt;/span&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Copy that URL and paste it on the CloudFront Distribution page’s&amp;nbsp;&lt;strong&gt;Origin Domain Name&amp;nbsp;&lt;/strong&gt;input field and click anywhere outside. It will load the necessary information into the other input fields.&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="297" class="wp-image-4572" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_xteYAXPP9Ywx-WxtemvI1w-1.webp?width=700&amp;amp;height=297&amp;amp;name=1_xteYAXPP9Ywx-WxtemvI1w-1.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;Paste the URL in this input box&lt;/span&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now let’s set up the other fields that we need. We will keep the default value for the following fields:&amp;nbsp;&lt;strong&gt;Enable Origin Shield, Origin Connection Attempts, Origin Connection Timeout, Smooth Streaming, Restrict Viewer Access(Use Signed URLs or Signed Cookies), Compress Objects Automatically, Supported HTTP Versions, Enable IPv6.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;So let’s start customizing the&amp;nbsp;&lt;strong&gt;Default Cache Behavior Settings&lt;/strong&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class="wp-block-list"&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;1st of all, we will change the&amp;nbsp;&lt;strong&gt;Viewer Protocol Policy&amp;nbsp;&lt;/strong&gt;settings. You can keep it as it is, but it’s recommended to change it to&amp;nbsp;&lt;em&gt;Redirect HTTP to HTTPS.&lt;/em&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;2nd, as our current website doesn’t have any PUT, POST, or DELETE operations, we will not change&amp;nbsp;&lt;strong&gt;Allowed HTTP Methods.&amp;nbsp;&lt;/strong&gt;But if you have a form or you communicate with an API, then you need to select the&amp;nbsp;&lt;em&gt;GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE&amp;nbsp;&lt;/em&gt;option.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;3rd, for the&amp;nbsp;&lt;strong&gt;Cache and origin request settings,&amp;nbsp;&lt;/strong&gt;we’ll change it to&amp;nbsp;&lt;em&gt;Use legacy cache settings&amp;nbsp;&lt;/em&gt;as we don’t want to keep any cache. If you want to keep it, don’t change the settings.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;If in the 3rd one, you selected the&amp;nbsp;&lt;em&gt;Use legacy cache settings,&amp;nbsp;&lt;/em&gt;then you will get an&amp;nbsp;&lt;strong&gt;Object Caching&amp;nbsp;&lt;/strong&gt;option. Which we will change to&amp;nbsp;&lt;em&gt;Customize&amp;nbsp;&lt;/em&gt;and then set the&amp;nbsp;&lt;strong&gt;Minimum TTL, Maximum TTL, Default TTL&amp;nbsp;&lt;/strong&gt;to 0 (zero). This will help the users to get up-to-date content each time they reload the page.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;This is the end result so far that we have implemented in the distribution page:&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="697" class="wp-image-4573" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_PLL1P8up4KLYD7NxVvabBg.webp?width=700&amp;amp;height=697&amp;amp;name=1_PLL1P8up4KLYD7NxVvabBg.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;The settings we implemented so far in the previous steps&lt;/span&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Now it’s time for the&amp;nbsp;&lt;strong&gt;Distribution Settings&lt;/strong&gt;&amp;nbsp;part. In this part, we will actually keep most of the things as it is, but this is the place where we will set up the custom domain. You can do that later so we will go through the process for now and keep all the default values. Just click&amp;nbsp;&lt;strong&gt;Create Distribution&lt;/strong&gt;&amp;nbsp;at the bottom and you are done!!&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;You will be taken to the CloudFront home page and you will find the distribution you just created.&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="95" class="wp-image-4574" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_bURak5PydL5uFUgDka4SPA.webp?width=700&amp;amp;height=95&amp;amp;name=1_bURak5PydL5uFUgDka4SPA.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;You will find the distribution on the CloudFront home page&lt;/span&gt;  
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;It takes some time for the distribution to be deployed for the first time. When it’s done, you will the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Status&amp;nbsp;&lt;/em&gt;&lt;/strong&gt;as&amp;nbsp;&lt;strong&gt;Deployed&lt;/strong&gt;. When that is ready, you can copy the&amp;nbsp;&lt;strong&gt;Domain Name&amp;nbsp;&lt;/strong&gt;and paste it in the browser and you will see it’s showing the website you hosted on the S3 bucket! So now you don’t have to remember the long S3 bucket hosting URL just to visit the website.&lt;/span&gt;&lt;/p&gt; 
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="132" class="wp-image-4575" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_G-vSDfvUbmVAv-FB_rYucQ.webp?width=700&amp;amp;height=132&amp;amp;name=1_G-vSDfvUbmVAv-FB_rYucQ.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;Use the URL from the domain name to visit the website.&lt;/span&gt;  
      &lt;span style="font-size: 16px;"&gt;&lt;img width="700" height="469" class="wp-image-4576" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_dvJWalj6hALBjhYKVwDpxw.webp?width=700&amp;amp;height=469&amp;amp;name=1_dvJWalj6hALBjhYKVwDpxw.webp" alt=""&gt;&lt;/span&gt; 
      &lt;span style="font-size: 16px;"&gt;Website loading using the Domain name from the CloudFront&lt;/span&gt;  
      &lt;h2 class="wp-block-heading"&gt;Setting up Custom Domain&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;For setting the custom domain, we need two things.&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;A registered domain and access to that domain’s DNS setting or access to the mails for that domain.&lt;/li&gt; 
       &lt;li&gt;A custom SSL certificate generated from AWS&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;We’ll assume you already have a domain registered somewhere. And you have access to your&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;DNS settings&lt;/a&gt;. But if you don’t have access to&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;DNS&lt;/a&gt;, then it’s alright too, as we will show you how to get registered using email as well.&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;To get the SSL Certificate, if you already don’t have one, you can just click the&amp;nbsp;&lt;strong&gt;Request or Import a Certificate with ACM&amp;nbsp;&lt;/strong&gt;from the distribution page.&lt;/p&gt; 
      &lt;img width="700" height="348" class="wp-image-4577" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_IuZltH4OpNk5OiOb6yJV_A.webp?width=700&amp;amp;height=348&amp;amp;name=1_IuZltH4OpNk5OiOb6yJV_A.webp" alt=""&gt;Or you can also directly to the&amp;nbsp;
      &lt;a href="https://console.aws.amazon.com/acm/home?region=us-east-1#/wizard/"&gt;&lt;strong&gt;Request Certificate&lt;/strong&gt;&lt;/a&gt;page. 
      &lt;img width="700" height="233" class="wp-image-4578" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_-sDs4QUpeyJmmZP-cIlIqQ.webp?width=700&amp;amp;height=233&amp;amp;name=1_-sDs4QUpeyJmmZP-cIlIqQ.webp" alt=""&gt; Request custom SSL Certificate page  
      &lt;p style="font-size: 16px;"&gt;Enter your custom domain name and press&amp;nbsp;&lt;strong&gt;Next.&lt;/strong&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;Then you will be taken to the&amp;nbsp;&lt;strong&gt;Select validation method&amp;nbsp;&lt;/strong&gt;page, where you will get two types of validation method:&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;DNS validation:&amp;nbsp;&lt;/strong&gt;It’s the most used one. It requires the user to go to the&amp;nbsp;&lt;a href="https://www.wpbeginner.com/glossary/dns/"&gt;domain DNS settings&lt;/a&gt;&amp;nbsp;page, then adding a new&amp;nbsp;&lt;a href="https://en.wikipedia.org/wiki/CNAME_record"&gt;&lt;strong&gt;CNAME&lt;/strong&gt;&amp;nbsp;record&lt;/a&gt;.&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Email validation:&amp;nbsp;&lt;/strong&gt;It uses some pre-configured email address to send you a validation email where you will be asked to verify that you requested the SSL certificate. If you accept that, then it will create an ACM SSL certificate in AWS. The email addresses are:&lt;br&gt;* postmaster@yourdomain.com&lt;br&gt;* hostmaster@yourdomain.com&lt;br&gt;* admin@yourdomain.com&lt;br&gt;* webmaster@yourdomain.com&lt;br&gt;* administrator@yourdomain.com&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;We will just briefly walk you through both of the ways just in a bit. But for now, let’s continue by selecting the&amp;nbsp;&lt;strong&gt;&lt;em&gt;Email validation&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;option as it is the easy one.&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;In the next step, just press&amp;nbsp;&lt;strong&gt;Review&lt;/strong&gt;&amp;nbsp;and you will be given a final checkup.&lt;/p&gt; 
      &lt;img width="700" height="252" class="wp-image-4579" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_i76tvu8UzXFt1GdnPVISgA.webp?width=700&amp;amp;height=252&amp;amp;name=1_i76tvu8UzXFt1GdnPVISgA.webp" alt=""&gt; Make sure everything is in place  
      &lt;p style="font-size: 16px;"&gt;Now hit&amp;nbsp;&lt;strong&gt;Confirm&lt;/strong&gt;&amp;nbsp;and it’s ready to go. AWS will send you an email for the confirmation on the pre-configured email addresses as mentioned before.&lt;/p&gt; 
      &lt;img width="700" height="237" class="wp-image-4580" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_i_MmluRKURVjGl8v7bLV8Q.webp?width=700&amp;amp;height=237&amp;amp;name=1_i_MmluRKURVjGl8v7bLV8Q.webp" alt=""&gt;
      &lt;span style="background-color: transparent;"&gt;Email is sent to the shown email addresses&lt;/span&gt; 
      &lt;p style="font-size: 16px;"&gt;Until you verify your email or set up the DNS, you will see the verification status as&amp;nbsp;&lt;em&gt;Pending validation&lt;/em&gt;.&lt;/p&gt; 
      &lt;img width="700" height="343" class="wp-image-4581" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_owIY8J2Wu3NkIxlnWp1pzw.webp?width=700&amp;amp;height=343&amp;amp;name=1_owIY8J2Wu3NkIxlnWp1pzw.webp" alt=""&gt; Waiting for confirmation  
      &lt;p style="font-size: 16px;"&gt;This is how a verification email looks like:&lt;/p&gt; 
      &lt;img width="700" height="455" class="wp-image-4582" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_9PKbITf8rAEXx4_Cb6TLDQ.webp?width=700&amp;amp;height=455&amp;amp;name=1_9PKbITf8rAEXx4_Cb6TLDQ.webp" alt=""&gt; The verification email from AWS  
      &lt;p style="font-size: 16px;"&gt;Just press the&amp;nbsp;&lt;strong&gt;Amazon Certificate Approvals&amp;nbsp;&lt;/strong&gt;link or copy and paste the URL on any browser and it will show you the message again. Hit the&amp;nbsp;&lt;strong&gt;I Approve&lt;/strong&gt;&amp;nbsp;button and you are all set!&lt;br&gt;&lt;br&gt;You can find that on the SSL certificate page as well if you refresh it.&lt;/p&gt; 
      &lt;img width="700" height="59" class="wp-image-4583" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_reVewHKhzMm6L7v5v8GhQw.webp?width=700&amp;amp;height=59&amp;amp;name=1_reVewHKhzMm6L7v5v8GhQw.webp" alt=""&gt; 
      &lt;strong&gt;The domain SSL certificate is created&lt;/strong&gt; 
      &lt;br&gt;
      &lt;span style="background-color: transparent;"&gt;For some domain/hosting platform, the Email Validation doesn’t work. If you find that the domain is not working, try using the DNS Validation instead of Email Validation. The DNS CNAME record-setting differs for different vendors. So we can’t cover that here.&lt;/span&gt;  
      &lt;p style="font-size: 16px;"&gt;&lt;strong&gt;DNS validation Process&lt;br&gt;&lt;/strong&gt;In case you selected DNS instead of Email, you will have to follow a different route. In that case, after you&amp;nbsp;&lt;strong&gt;Confirm&amp;nbsp;&lt;/strong&gt;the process, you will get this:&lt;/p&gt; 
      &lt;img width="1024" height="323" class="wp-image-4584" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_Hxx3mDmIW0GzaPq7j_5GOg.webp?width=1024&amp;amp;height=323&amp;amp;name=1_Hxx3mDmIW0GzaPq7j_5GOg.webp" alt=""&gt;
      &lt;strong style="background-color: transparent;"&gt;CNAME record credentials&lt;/strong&gt; 
      &lt;strong&gt;&amp;nbsp;&lt;/strong&gt; You will find the credentials you need to set in the domain DNS system as a CNAME record. You can also download that credentials CSV file if you want to do it later or send it to someone who has access to the DNS settings. After the CNAME record is created, it will show the status as&amp;nbsp;
      &lt;strong&gt;&lt;em&gt;issued&lt;/em&gt;&lt;/strong&gt;&amp;nbsp;in the SSL certificate list. 
      &lt;p style="font-size: 16px;"&gt;When setting up the CNAME, you actually will need to set up 2 CNAME records.&lt;/p&gt; 
      &lt;ol class="wp-block-list" style="font-size: 16px;"&gt; 
       &lt;li&gt;For verifying the custom SSL certificate. In this case, the name and value you will get from the AWS, the image we’ve shown just before.&lt;/li&gt; 
       &lt;li&gt;For redirecting to the CloudFront when we enter the domain on a browser. The name for this one will be the&amp;nbsp;&lt;em&gt;custom domain name&lt;/em&gt;&amp;nbsp;you want to set up for the website (in our case&amp;nbsp;&lt;em&gt;reactaws.apphousebd.com&lt;/em&gt;) and the value will be the CloudFront distribution domain name. Keep in mind the&amp;nbsp;&lt;em&gt;custom domain name&amp;nbsp;&lt;/em&gt;you set up for as the name, because it will be needed later when setting up the&amp;nbsp;&lt;strong&gt;Alternate Domain Names (CNAMEs)&amp;nbsp;&lt;/strong&gt;field.&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;img width="700" height="217" class="wp-image-4585" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_cq6CmLJwHjUzEvO2R56Anw.webp?width=700&amp;amp;height=217&amp;amp;name=1_cq6CmLJwHjUzEvO2R56Anw.webp" alt=""&gt; 
      &lt;strong&gt;CloudFront distribution domain name&lt;br&gt;&lt;/strong&gt; It may take some time to verify the domain with DNS validation, so wait at least 5–10 mins before trying again. 
      &lt;h2 class="wp-block-heading"&gt;Setting the Custom domain in CloudFront&lt;/h2&gt; 
      &lt;p&gt;Now for the moment that we are building up the whole thing!&lt;/p&gt; 
      &lt;p&gt;Go to the CloudFront distribution page and select&amp;nbsp;&lt;em&gt;Edit&lt;/em&gt;.&lt;/p&gt; 
      &lt;img width="1024" height="579" class="wp-image-4586" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_4jtIzdBorMeo_ExTJu5hGg.webp?width=1024&amp;amp;height=579&amp;amp;name=1_4jtIzdBorMeo_ExTJu5hGg.webp" alt=""&gt; 
      &lt;ul class="wp-block-list"&gt; 
       &lt;li&gt;There in the&amp;nbsp;&lt;strong&gt;Alternate Domain Names (CNAMEs)&amp;nbsp;&lt;/strong&gt;field, enter the custom domain name of which you have already created an SSL certificate.&lt;/li&gt; 
       &lt;li&gt;After that, select the&amp;nbsp;&lt;em&gt;Custom SSL Certificate (example.com)&amp;nbsp;&lt;/em&gt;option for&amp;nbsp;&lt;strong&gt;SSL Certificate.&amp;nbsp;&lt;/strong&gt;There if you click on the input box, you will find the SSL certificate you created. Select the one with the domain you entered in the previous step.&lt;/li&gt; 
       &lt;li&gt;Enter&amp;nbsp;&lt;em&gt;index.html&lt;/em&gt;&amp;nbsp;in the&amp;nbsp;&lt;strong&gt;Default Root Object&amp;nbsp;&lt;/strong&gt;input field&lt;/li&gt; 
       &lt;li&gt;Keep the other thins as it is.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;img width="700" height="713" class="wp-image-4587" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/1_pC6jFpLnnU-4vqCDENCWDg.webp?width=700&amp;amp;height=713&amp;amp;name=1_pC6jFpLnnU-4vqCDENCWDg.webp" alt=""&gt; Distribution setting after everything is set up  
      &lt;p&gt;Hit&amp;nbsp;&lt;strong&gt;Yes, Edit&lt;/strong&gt;&amp;nbsp;and that’s it. Finally, everything is over!!! Just wait until the status of the CloudFront distribution is changed from&amp;nbsp;&lt;strong&gt;In Progress&lt;/strong&gt;&amp;nbsp;to&amp;nbsp;&lt;strong&gt;Deployed&amp;nbsp;&lt;/strong&gt;and then you can test the website with the custom domain you just set.&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;Well, it’s been a long way since the start. But I believe you now have enough knowledge about how to deploy your own or any other person’s React website on AWS. Hope this post helps you in your exciting coding/developer life.&lt;/p&gt; 
      &lt;p&gt;Happy coding!&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fpublishing-a-react-website-on-aws-with-aws-amplify-and-aws-cloudfront-with-custom-domain-part-2&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>AWS</category>
      <pubDate>Fri, 24 Apr 2026 09:52:07 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/publishing-a-react-website-on-aws-with-aws-amplify-and-aws-cloudfront-with-custom-domain-part-2</guid>
      <dc:date>2026-04-24T09:52:07Z</dc:date>
      <dc:creator>Eimon Hossain Taief</dc:creator>
    </item>
    <item>
      <title>Two Heads, One Keyboard: The Magic of Pair Programming - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/two-heads-one-keyboard-the-magic-of-pair-programming</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/two-heads-one-keyboard-the-magic-of-pair-programming" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/Two-Heads-One-Keyboard-The-Magic-of-Pair-Programming.webp" alt="Two Heads, One Keyboard: The Magic of Pair Programming - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96618"&gt; 
  &lt;div class="elementor-element elementor-element-4f9cb788 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-5b707d9 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Introduction&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;We programmers often think that programming is&amp;nbsp; a solitary job. But it is more of a social job. Developers are more productive when they are inspired and collaborate with their teams. This entails providing developers with tools and resources that will enable them to cooperate more effectively with other developers.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;We can achieve this by a variety of&amp;nbsp; tactics and one of the most widely regarded methodologies is pair programming. At first glance one can identify these tactics as to improve productivity but it also adds a pair with your colleague, besides producing code with fewer bugs, code with more readability, better solutions of the problem and sharing knowledge.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;What is Pair Programming?&lt;/h2&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-b6f30d2 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-54e0e2d elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair Programming is a programming methodology where two programmers are working together on a single task simultaneously and collaboratively. While doing the task they share their thoughts on how to solve the problem efficiently. And ultimately they came up with an optimum solution for the problem. There are many ways to do pair programming. One of the widely regarded patterns is having two roles, one is driver and the other one is navigator.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;The Driver Navigator Style&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;One of the most widely used styles as far as pair programming is concerned is the driver-navigator.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Its term comes from how two travelers may manage a vehicle drive through a new region. The driver concentrates on tactical issues concerning the mechanics of the action. This includes using the gas and brake pedals, moving the wheel, and keeping a lookout for hazards and other vehicles. The navigator, on the other hand, focuses more on the larger picture. How long will we be on this highway until we have to exit? Does my phone alert me to any unforeseen traffic jams?&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;When you apply the metaphor to programming, the driver handles typing, file navigation, and basic implementation. The navigator, on the other hand, considers wider issues and checks for errors. Is this technique consistent with the architecture? Are we potentially duplicating an existing implementation? Is this a dead end?&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Driver-navigator works best with two specialists who can switch responsibilities. It works well with both an expert and a novice. This occurs most readily when the expert navigates because a novice navigator may sit idly while the expert does both jobs.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Pair Partner&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;A pair partner is one of the two developers who is actively doing the same task in real time using the same workstation. A pair partner may alternate between being a driver and a navigator. As both pair programmers will actively do a single task it is important to have a good pair partner. A good pair partner is a blessing in disguise, often bringing unexpected benefits that enhance the development process.&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Advantages of a Good Pair Programmer: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Having a good pair partner can speed up productivity. The continuous feedback loop and collaborative problem solving actually reduce the time spent in debugging and rework. They can brainstorm the solution in real time resulting in an optimum solution.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Emotional and Mental Awareness: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;An attentive pair partner is always aware of their other’s mental and emotional conditions and may spot symptoms of worry, exhaustion, or tension. Keeping a safe and effective work environment requires this insight. A quick coffee break or some lighthearted talk can help ease tensions when one partner senses that the other is feeling overburdened or anxious. These modest yet thoughtful deeds promote a supportive environment, relieve tension, and act as a mental reset.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Benefits of Breaks and Informal Interaction: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Keep the screen away from the eyesight, both partners can return to their task with a refreshed mind and renewed energy. Additionally, some informal chats or some funny jokes can strengthen their bond, making the collaboration job more enjoyable and productive. This kind of behavior not only boosts morale but also enhances overall productivity, as both of the pair partners ensure that they will operate at their best as possible. So in the long run such mindful interactions with the pair partner contribute a lot.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Long-Term Contributions: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;A good pair partner encourages continuous improvement. Through constructive feedback and shared learning experiences, both partners can continuously refine their skills and approaches. This commitment to ongoing development can lead to long-term benefits, making each subsequent project more efficient and successful.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;How to Find a Pair Partner&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;As previously stated, having a decent companion is a blessing in disguise. If one can find a decent companion, development can be joyful; otherwise, it can be a disaster. Because if one’s partner is not open to new experiences, heated fights may arise. So it is important to pick one that is appropriate. Here are some strategies to help you find the right person to pair with:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Seek Experience and Openness: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If you’re doing pair programming for the first time, it’s a good idea to find someone who has done it before.&amp;nbsp; An Experienced guy can guide you through the whole process and also tell you the best practices one should follow while pair programming.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Compatibility and Communication: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It is also vital to locate a partner who is compatible with you. Someone with whom one may work despite any fear or awkwardness associated with asking dumb questions. Effective pair programming relies on open communication and mutual respect rather than ego or criticism.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Shared Goals and Learning Mindset: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It is adamant to choose a partner who has a similar mindset of learning as yours. Pair programming is more than simply writing code together. It is also about learning from another person’s strengths and limitations. Working together to solve problems and besides growing as developers.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is popular nowadays since it allows people to collaborate. They begin chatting for the sake of development, resulting in a greater bonding and understanding, which will help them solve more problem-related issues in the near future since they understand each other properly and know each other’s strong and weak areas.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Why Pair Programming is Necessary&lt;br&gt;&lt;br&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;strong&gt;The Role of Pair Programming&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;There can always be times that a feature needs to implement as soon as possible. We developers can work round the clock, push ourself to do the coding and deliver the features under tight deadlines. But how productive will it be if the work is done all alone? The code&amp;nbsp; can have some technical flaws, hidden bugs and performance issues. After deploying the codes in production and after a few months if those issues arise solving them will be a real time killing job and will cost more time as well as effort.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Here pair programming comes as a savior. Pair programming doesn’t mean that to produce more code in a short passage of time. It’s not like if one person can do the job within a day, then with a pair partner the job will be finished within a half day. Pair programming is about knowledge sharing.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Enhancing Code Quality and Maintainability: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;The code should be easy to read and behave as expected. We need to bear in mind that about the next developer who will maintain the code. To do that one needs to pair with others so that the code should be as easy as it gets and there should always be fewer bugs and also behave as expected. The quality of code produced by two people is inherently more readable and maintainable because it benefits from the mutual understanding and scrutiny of both partners.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Collaborative Problem-Solving: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;When two people are thinking about the same problem, they bring diverse perspectives and ideas to the table. This collaborative approach leads to more robust solutions, as each partner can identify potential issues and improvements that the other might miss. This shared responsibility and combined expertise significantly reduce the likelihood of errors and enhance the overall quality of the code.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Pair Programming Template&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming requires adhering to templates, which are rules to follow. If a template is not defined, pair programming is likely to fail. There are no hard and fast rules for following particular rules in pair programming; instead, the rules should be set by the pair partners and added based on mutual understanding. Here are some basic principles that a pair partner can follow, albeit it all depends on their attitudes.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;strong&gt;Basic Principles for Pair Programming&lt;/strong&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define the period of time.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define a precise goal as what must be accomplished in that amount of time.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define how often and for how long you will switch rules.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Track an alarm for both break and switch rules.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Every interruption during the pair programming should be disregarded.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Respect one other’s opinions and actively listen to one another.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Use collaboration tools.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Create a communication channel with your pair companion.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Review today’s session and make a schedule for the next one.&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;2. &lt;strong&gt;Ideal Length of Pair Programming Session&lt;/strong&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;It is obvious that there will always be a deadline for a task . That does not mean that you have to work for hours with your companion. It is important to take breaks between works so that you may refocus your efforts and generate optimum solutions in an effective manner. As a result, setting time limits between sessions is important. However, there are no hard and fast regulations for a time restriction. It all depends on the pair partner. They should impose a time restriction of 30 minutes, 60 minutes, or something in between. After each session, pair partners&amp;nbsp; should take a 5-15 minute rest, depending on their pair partner. Following the break, they should resume the session.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is not intended to be used just to prolong the session. The goal is to make the session as beneficial and productive as possible. Smaller sessions are OK as long as they are fruitful. When one has more expertise with sessions, it becomes easier to have longer sessions that can last several hours. However, it is important to remember to shift responsibilities between sessions, regardless of their length. So that each pair mate can experience each position.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Taking breaks does not mean one is relaxing. Breaks provides an opportunity&amp;nbsp; to give one’s partner time to reflect on its work. Addressing issues which he/she encounters and coming up with new ideas. A quick chit chat about anything which is not related to work or simply removing yourself from the computer screen can enhance creativity and problem solving skills. Breaks can also help to prevent burnout, which benefits both couples’ emotional and physical health.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Advantages of Pair Programming&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;The main advantage of the process is that while the navigator is navigating each and every line of code, this type of inspection enables the early detection of bugs before the code reviews and which saves more time. Some more advantages are:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Fewer Bugs :&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As an old saying says, two heads are better than one. As Two heads are working together there is always room that there should be fewer bugs than usual.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Focused Workflow:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As two people are working together there should be more focus and attention to work than before. If someone loses focus there always will be one who will help to refocus.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Knowledge Sharing:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When two people are thinking about the same problem and they will share their perspective regarding the problem resulting in sharing their point of view to each other.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Less Code Reviews:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When two people are working together and one person is continuously navigating the code. So there are high chances that the bugs are identified at the first point resulting in most code reviews being done on the first part.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Code Quality:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; It also improves code quality as the patterns always tend to follow the industry best practices.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Minimize Your Stuckness:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;&amp;nbsp; While working , one may naturally become stuck several times. In these situations, one may contact their partner for assistance. Additionally, the pair partner’s&amp;nbsp; can&amp;nbsp; identify when someone is heading in the wrong path and help them change course.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Enhancing Focus: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Some developers find lonely programming a boring task as sometimes the developer can be out of focus. In that case the pair programming enables us to focus on the task completely as two people are actively participating on a single task. If any of the partners feels boredom or out of focus his/her pair partner should always try to keep him/her in focus and out of boredom which enables higher productivity than the usual lonely programming.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Continuous Learning:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Engaging in pair programming allows developers to continuously learn from each other. Partners can share new techniques, tools, and insights, contributing to ongoing professional growth and development.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;So pair programming unlocks more productivity, better collaboration, higher quality, better codes, and more sustainable development practices as well as personal growth.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Pair programming is a productive approach that has been utilized for years in the software development industry. It may enhance teamwork and information exchange, among other areas of your job. Naturally, there are some obstacles along the way, but even your first pairing sessions may be successful if you follow these couple programming principles.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is something you should try with your team if you haven’t before. Additionally, be sure you read the instructions about getting started with pair programming if this is your first time. This will improve team communication, add enjoyment to your job, and, of course, write better code.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96618"&gt; 
  &lt;div class="elementor-element elementor-element-4f9cb788 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-5b707d9 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Introduction&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;We programmers often think that programming is&amp;nbsp; a solitary job. But it is more of a social job. Developers are more productive when they are inspired and collaborate with their teams. This entails providing developers with tools and resources that will enable them to cooperate more effectively with other developers.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;We can achieve this by a variety of&amp;nbsp; tactics and one of the most widely regarded methodologies is pair programming. At first glance one can identify these tactics as to improve productivity but it also adds a pair with your colleague, besides producing code with fewer bugs, code with more readability, better solutions of the problem and sharing knowledge.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;What is Pair Programming?&lt;/h2&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-b6f30d2 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="620" height="456" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image1-1-2.png?width=620&amp;amp;height=456&amp;amp;name=image1-1-2.png" class="attachment-large size-large wp-image-96623" alt="pair programming"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-54e0e2d elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair Programming is a programming methodology where two programmers are working together on a single task simultaneously and collaboratively. While doing the task they share their thoughts on how to solve the problem efficiently. And ultimately they came up with an optimum solution for the problem. There are many ways to do pair programming. One of the widely regarded patterns is having two roles, one is driver and the other one is navigator.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;The Driver Navigator Style&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;One of the most widely used styles as far as pair programming is concerned is the driver-navigator.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Its term comes from how two travelers may manage a vehicle drive through a new region. The driver concentrates on tactical issues concerning the mechanics of the action. This includes using the gas and brake pedals, moving the wheel, and keeping a lookout for hazards and other vehicles. The navigator, on the other hand, focuses more on the larger picture. How long will we be on this highway until we have to exit? Does my phone alert me to any unforeseen traffic jams?&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;When you apply the metaphor to programming, the driver handles typing, file navigation, and basic implementation. The navigator, on the other hand, considers wider issues and checks for errors. Is this technique consistent with the architecture? Are we potentially duplicating an existing implementation? Is this a dead end?&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Driver-navigator works best with two specialists who can switch responsibilities. It works well with both an expert and a novice. This occurs most readily when the expert navigates because a novice navigator may sit idly while the expert does both jobs.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Pair Partner&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;A pair partner is one of the two developers who is actively doing the same task in real time using the same workstation. A pair partner may alternate between being a driver and a navigator. As both pair programmers will actively do a single task it is important to have a good pair partner. A good pair partner is a blessing in disguise, often bringing unexpected benefits that enhance the development process.&amp;nbsp;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Advantages of a Good Pair Programmer: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Having a good pair partner can speed up productivity. The continuous feedback loop and collaborative problem solving actually reduce the time spent in debugging and rework. They can brainstorm the solution in real time resulting in an optimum solution.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Emotional and Mental Awareness: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;An attentive pair partner is always aware of their other’s mental and emotional conditions and may spot symptoms of worry, exhaustion, or tension. Keeping a safe and effective work environment requires this insight. A quick coffee break or some lighthearted talk can help ease tensions when one partner senses that the other is feeling overburdened or anxious. These modest yet thoughtful deeds promote a supportive environment, relieve tension, and act as a mental reset.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Benefits of Breaks and Informal Interaction: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Keep the screen away from the eyesight, both partners can return to their task with a refreshed mind and renewed energy. Additionally, some informal chats or some funny jokes can strengthen their bond, making the collaboration job more enjoyable and productive. This kind of behavior not only boosts morale but also enhances overall productivity, as both of the pair partners ensure that they will operate at their best as possible. So in the long run such mindful interactions with the pair partner contribute a lot.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Long-Term Contributions: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;A good pair partner encourages continuous improvement. Through constructive feedback and shared learning experiences, both partners can continuously refine their skills and approaches. This commitment to ongoing development can lead to long-term benefits, making each subsequent project more efficient and successful.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;How to Find a Pair Partner&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;As previously stated, having a decent companion is a blessing in disguise. If one can find a decent companion, development can be joyful; otherwise, it can be a disaster. Because if one’s partner is not open to new experiences, heated fights may arise. So it is important to pick one that is appropriate. Here are some strategies to help you find the right person to pair with:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Seek Experience and Openness: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If you’re doing pair programming for the first time, it’s a good idea to find someone who has done it before.&amp;nbsp; An Experienced guy can guide you through the whole process and also tell you the best practices one should follow while pair programming.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Compatibility and Communication: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It is also vital to locate a partner who is compatible with you. Someone with whom one may work despite any fear or awkwardness associated with asking dumb questions. Effective pair programming relies on open communication and mutual respect rather than ego or criticism.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Shared Goals and Learning Mindset: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It is adamant to choose a partner who has a similar mindset of learning as yours. Pair programming is more than simply writing code together. It is also about learning from another person’s strengths and limitations. Working together to solve problems and besides growing as developers.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is popular nowadays since it allows people to collaborate. They begin chatting for the sake of development, resulting in a greater bonding and understanding, which will help them solve more problem-related issues in the near future since they understand each other properly and know each other’s strong and weak areas.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Why Pair Programming is Necessary&lt;br&gt;&lt;br&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;strong&gt;The Role of Pair Programming&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;There can always be times that a feature needs to implement as soon as possible. We developers can work round the clock, push ourself to do the coding and deliver the features under tight deadlines. But how productive will it be if the work is done all alone? The code&amp;nbsp; can have some technical flaws, hidden bugs and performance issues. After deploying the codes in production and after a few months if those issues arise solving them will be a real time killing job and will cost more time as well as effort.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Here pair programming comes as a savior. Pair programming doesn’t mean that to produce more code in a short passage of time. It’s not like if one person can do the job within a day, then with a pair partner the job will be finished within a half day. Pair programming is about knowledge sharing.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Enhancing Code Quality and Maintainability: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;The code should be easy to read and behave as expected. We need to bear in mind that about the next developer who will maintain the code. To do that one needs to pair with others so that the code should be as easy as it gets and there should always be fewer bugs and also behave as expected. The quality of code produced by two people is inherently more readable and maintainable because it benefits from the mutual understanding and scrutiny of both partners.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Collaborative Problem-Solving: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;When two people are thinking about the same problem, they bring diverse perspectives and ideas to the table. This collaborative approach leads to more robust solutions, as each partner can identify potential issues and improvements that the other might miss. This shared responsibility and combined expertise significantly reduce the likelihood of errors and enhance the overall quality of the code.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Pair Programming Template&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming requires adhering to templates, which are rules to follow. If a template is not defined, pair programming is likely to fail. There are no hard and fast rules for following particular rules in pair programming; instead, the rules should be set by the pair partners and added based on mutual understanding. Here are some basic principles that a pair partner can follow, albeit it all depends on their attitudes.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;strong&gt;Basic Principles for Pair Programming&lt;/strong&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define the period of time.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define a precise goal as what must be accomplished in that amount of time.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Define how often and for how long you will switch rules.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Track an alarm for both break and switch rules.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Every interruption during the pair programming should be disregarded.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Respect one other’s opinions and actively listen to one another.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Use collaboration tools.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Create a communication channel with your pair companion.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Review today’s session and make a schedule for the next one.&amp;nbsp;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;2. &lt;strong&gt;Ideal Length of Pair Programming Session&lt;/strong&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;It is obvious that there will always be a deadline for a task . That does not mean that you have to work for hours with your companion. It is important to take breaks between works so that you may refocus your efforts and generate optimum solutions in an effective manner. As a result, setting time limits between sessions is important. However, there are no hard and fast regulations for a time restriction. It all depends on the pair partner. They should impose a time restriction of 30 minutes, 60 minutes, or something in between. After each session, pair partners&amp;nbsp; should take a 5-15 minute rest, depending on their pair partner. Following the break, they should resume the session.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is not intended to be used just to prolong the session. The goal is to make the session as beneficial and productive as possible. Smaller sessions are OK as long as they are fruitful. When one has more expertise with sessions, it becomes easier to have longer sessions that can last several hours. However, it is important to remember to shift responsibilities between sessions, regardless of their length. So that each pair mate can experience each position.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Taking breaks does not mean one is relaxing. Breaks provides an opportunity&amp;nbsp; to give one’s partner time to reflect on its work. Addressing issues which he/she encounters and coming up with new ideas. A quick chit chat about anything which is not related to work or simply removing yourself from the computer screen can enhance creativity and problem solving skills. Breaks can also help to prevent burnout, which benefits both couples’ emotional and physical health.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Advantages of Pair Programming&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;The main advantage of the process is that while the navigator is navigating each and every line of code, this type of inspection enables the early detection of bugs before the code reviews and which saves more time. Some more advantages are:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Fewer Bugs :&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As an old saying says, two heads are better than one. As Two heads are working together there is always room that there should be fewer bugs than usual.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Focused Workflow:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As two people are working together there should be more focus and attention to work than before. If someone loses focus there always will be one who will help to refocus.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Knowledge Sharing:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When two people are thinking about the same problem and they will share their perspective regarding the problem resulting in sharing their point of view to each other.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Less Code Reviews:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When two people are working together and one person is continuously navigating the code. So there are high chances that the bugs are identified at the first point resulting in most code reviews being done on the first part.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Code Quality:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; It also improves code quality as the patterns always tend to follow the industry best practices.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Minimize Your Stuckness:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;&amp;nbsp; While working , one may naturally become stuck several times. In these situations, one may contact their partner for assistance. Additionally, the pair partner’s&amp;nbsp; can&amp;nbsp; identify when someone is heading in the wrong path and help them change course.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Enhancing Focus: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Some developers find lonely programming a boring task as sometimes the developer can be out of focus. In that case the pair programming enables us to focus on the task completely as two people are actively participating on a single task. If any of the partners feels boredom or out of focus his/her pair partner should always try to keep him/her in focus and out of boredom which enables higher productivity than the usual lonely programming.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Continuous Learning:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Engaging in pair programming allows developers to continuously learn from each other. Partners can share new techniques, tools, and insights, contributing to ongoing professional growth and development.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;So pair programming unlocks more productivity, better collaboration, higher quality, better codes, and more sustainable development practices as well as personal growth.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;Pair programming is a productive approach that has been utilized for years in the software development industry. It may enhance teamwork and information exchange, among other areas of your job. Naturally, there are some obstacles along the way, but even your first pairing sessions may be successful if you follow these couple programming principles.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Pair programming is something you should try with your team if you haven’t before. Additionally, be sure you read the instructions about getting started with pair programming if this is your first time. This will improve team communication, add enjoyment to your job, and, of course, write better code.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Ftwo-heads-one-keyboard-the-magic-of-pair-programming&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <category>Tips and hacks</category>
      <pubDate>Thu, 18 Dec 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/two-heads-one-keyboard-the-magic-of-pair-programming</guid>
      <dc:date>2025-12-18T18:00:00Z</dc:date>
      <dc:creator>Foisal Reza</dc:creator>
    </item>
    <item>
      <title>Case Study: Tackling a Complex Video Editing Feature Without Breaking Existing Functionality - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/case-study-tackling-a-complex-video-editing-feature-without-breaking-existing-functionality</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/case-study-tackling-a-complex-video-editing-feature-without-breaking-existing-functionality" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/Case-Study.webp" alt="Case Study: Tackling a Complex Video Editing Feature Without Breaking Existing Functionality - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97903"&gt; 
  &lt;div class="elementor-element elementor-element-85b972f e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-46b4b96 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The feature under development is a complex video editing operation involving significant logical and computational challenges, as well as a high number of potential usage patterns. This complexity required careful consideration of numerous use cases and edge cases to ensure reliability and scalability in the codebase.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;The Core Challenge: Preserving Stability Amid Ongoing Development&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The central challenge was clear from the beginning: how to implement new functionality without compromising the reliability of existing features. The original system already handled between ten to fifteen distinct use cases, each containing unique combinations of media states, clip transitions, user interactions, and data persistence requirements.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Every new modification risked introducing regressions, breaking features that previously worked flawlessly. Early attempts showed how fragile the balance was. A new feature might fix one scenario while inadvertently causing issues in another. This constant push and pull made progress uncertain and forced the team to look for a more sustainable strategy.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Manual verification of all scenarios after each code change quickly proved to be unmanageable. With so many combinations of user actions, browser contexts, and temporal states to account for, testing everything by hand would have taken days after each iteration. This became a bottleneck, limiting the team’s ability to move forward with confidence and slowing down development velocity.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;br&gt;Strategic Approach: Automating for Confidence&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To address this, &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;a structured automated testing approach&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; was introduced. Each new code addition was accompanied by comprehensive unit tests, including tests for boundary conditions.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This ensured that any regression was immediately detected, tests would pinpoint which case failed to meet expected outcomes. Maintaining parallel progress between production and test code allowed developers to iterate safely: if all tests passed, existing functionality remained intact, enabling focus on extending capabilities.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Equally important was the quality of the tests themselves. Tests were written to build genuine confidence in system behavior rather than to simply meet coverage metrics. Poorly designed tests may pass without providing assurance; meaningful tests reflect true system integrity and support reliable evolution of the code.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Outcome and Impact&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The feature is now complete and has demonstrated substantial improvement in development confidence and agility. Automated test coverage provided a safety net for change, enabling faster iteration without fear of regressions.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Breaking the problem into smaller, testable units proved essential for managing complexity. The result was a system that could evolve steadily while maintaining a high degree of reliability.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Conclusion: From Reactive Debugging to Proactive Assurance&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The successful implementation of this complex feature validated the effectiveness of embedding testing into the development process. Treating tests as an integral design component, rather than a final validation step, shifted the workflow from &lt;/span&gt;reactive debugging to proactive quality assurance.&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The result is a resilient, maintainable, and confidently extensible system, one that meets its functional goals while reflecting strong engineering maturity and process discipline.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97903"&gt; 
  &lt;div class="elementor-element elementor-element-85b972f e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-46b4b96 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The feature under development is a complex video editing operation involving significant logical and computational challenges, as well as a high number of potential usage patterns. This complexity required careful consideration of numerous use cases and edge cases to ensure reliability and scalability in the codebase.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;The Core Challenge: Preserving Stability Amid Ongoing Development&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The central challenge was clear from the beginning: how to implement new functionality without compromising the reliability of existing features. The original system already handled between ten to fifteen distinct use cases, each containing unique combinations of media states, clip transitions, user interactions, and data persistence requirements.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Every new modification risked introducing regressions, breaking features that previously worked flawlessly. Early attempts showed how fragile the balance was. A new feature might fix one scenario while inadvertently causing issues in another. This constant push and pull made progress uncertain and forced the team to look for a more sustainable strategy.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Manual verification of all scenarios after each code change quickly proved to be unmanageable. With so many combinations of user actions, browser contexts, and temporal states to account for, testing everything by hand would have taken days after each iteration. This became a bottleneck, limiting the team’s ability to move forward with confidence and slowing down development velocity.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;br&gt;Strategic Approach: Automating for Confidence&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To address this, &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;a structured automated testing approach&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; was introduced. Each new code addition was accompanied by comprehensive unit tests, including tests for boundary conditions.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This ensured that any regression was immediately detected, tests would pinpoint which case failed to meet expected outcomes. Maintaining parallel progress between production and test code allowed developers to iterate safely: if all tests passed, existing functionality remained intact, enabling focus on extending capabilities.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Equally important was the quality of the tests themselves. Tests were written to build genuine confidence in system behavior rather than to simply meet coverage metrics. Poorly designed tests may pass without providing assurance; meaningful tests reflect true system integrity and support reliable evolution of the code.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Outcome and Impact&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The feature is now complete and has demonstrated substantial improvement in development confidence and agility. Automated test coverage provided a safety net for change, enabling faster iteration without fear of regressions.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Breaking the problem into smaller, testable units proved essential for managing complexity. The result was a system that could evolve steadily while maintaining a high degree of reliability.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Conclusion: From Reactive Debugging to Proactive Assurance&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The successful implementation of this complex feature validated the effectiveness of embedding testing into the development process. Treating tests as an integral design component, rather than a final validation step, shifted the workflow from &lt;/span&gt;reactive debugging to proactive quality assurance.&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The result is a resilient, maintainable, and confidently extensible system, one that meets its functional goals while reflecting strong engineering maturity and process discipline.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fcase-study-tackling-a-complex-video-editing-feature-without-breaking-existing-functionality&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <pubDate>Wed, 12 Nov 2025 05:15:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/case-study-tackling-a-complex-video-editing-feature-without-breaking-existing-functionality</guid>
      <dc:date>2025-11-12T05:15:00Z</dc:date>
      <dc:creator>Craftsmen Software Maestro</dc:creator>
    </item>
    <item>
      <title>The Smart Way to Add Languages to Your Streaming Content (Without Breaking the Bank) - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/the-smart-way-to-add-languages-to-your-streaming-content-without-breaking-the-bank/termtech</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/the-smart-way-to-add-languages-to-your-streaming-content-without-breaking-the-bank/termtech" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/Blog_Thumbnail344-Dec-15-2025-11-12-55-2811-AM.webp" alt="The Smart Way to Add Languages to Your Streaming Content (Without Breaking the Bank) - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97807"&gt; 
  &lt;div class="elementor-element elementor-element-287921be e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-71572e41 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Global Streaming Dream vs. The Costly Reality&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;In today’s hyper-connected world, streaming platforms dream of reaching global audiences. Viewers expect content in&amp;nbsp;&lt;em class="my"&gt;their&lt;/em&gt;&amp;nbsp;language, and delivering that is no longer a luxury — it’s a necessity. But ask any video engineer about adding multiple languages to a large content library, and you’ll likely hear a sigh. Why? Because the traditional methods are often a budget-draining nightmare.&lt;/span&gt;&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;As a video engineer, I faced this challenge head-on. Expanding content globally meant dealing with the harsh reality of multiplying infrastructure costs.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Old Way: Expensive, Slow, and Inefficient&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;Traditionally, adding a new audio track or subtitle set meant going back to square one:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Re-encoding:&lt;/strong&gt;&amp;nbsp;Processing the&amp;nbsp;&lt;em class="my"&gt;entire&lt;/em&gt;&amp;nbsp;video file again for&amp;nbsp;&lt;em class="my"&gt;each&lt;/em&gt;&amp;nbsp;new language.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Duplication:&lt;/strong&gt;&amp;nbsp;Generating and storing complete, separate sets of video segments for every language variant.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Storage Bloat:&lt;/strong&gt;&amp;nbsp;Paying to store visually identical video content over and over.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Manifest Mayhem:&lt;/strong&gt;&amp;nbsp;Juggling complex sets of separate manifest files for each version.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;Imagine doing this for thousands of assets and ten different languages. The costs (storage, processing) and time commitment scale frighteningly fast, becoming a major bottleneck to global expansion.&lt;/span&gt;&lt;/p&gt; 
      &lt;blockquote class="nm nn no"&gt; 
       &lt;p class="ma mb my mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;em class="fs"&gt;“Adding languages traditionally meant re-encoding everything. For large libraries, costs spiraled out of control.”&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;/blockquote&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;A Smarter Approach: Dynamic Manifest Integration&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;I knew there had to be a better way. Instead of brute-forcing the problem, I looked at the elegance of modern streaming protocols like HLS and DASH. My solution leverages their flexibility through&amp;nbsp;&lt;strong class="mc ft"&gt;Dynamic Manifest Integration&lt;/strong&gt;.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;Think of a streaming manifest (like an HLS&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;.m3u8&lt;/code&gt;&amp;nbsp;or a DASH&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;.mpd&lt;/code&gt;&amp;nbsp;file) as a detailed “playlist” or “table of contents” that tells the video player exactly where to find the video, audio, and subtitle segments it needs to play.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;My approach cleverly modifies this playlist:&lt;/p&gt; 
      &lt;ol class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Keep One Video:&lt;/strong&gt;&amp;nbsp;I maintain just&amp;nbsp;&lt;em class="my"&gt;one&lt;/em&gt;&amp;nbsp;high-quality set of video segments. No visual duplication!&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Separate Audio/Subtitles:&lt;/strong&gt;&amp;nbsp;Audio tracks and subtitle files are processed and stored independently.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Update the Playlist:&lt;/strong&gt;&amp;nbsp;I dynamically update the&amp;nbsp;&lt;em class="my"&gt;manifest file&lt;/em&gt;&amp;nbsp;to simply&amp;nbsp;&lt;em class="my"&gt;point&lt;/em&gt;&amp;nbsp;to these external audio and subtitle components.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Seamless Experience:&lt;/strong&gt;&amp;nbsp;The player reads the updated manifest, presents the user with all available language options, and plays the correct combination using the&amp;nbsp;&lt;em class="my"&gt;same&lt;/em&gt;&amp;nbsp;video stream.&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;How It Works: A Peek Under the Hood (HLS &amp;amp; DASH)&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;The magic lies in specific tags within the manifest files.&lt;/p&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;strong class="mc ft"&gt;&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-weight: normal;"&gt;&lt;span class="mc ft"&gt;For HLS (HTTP Live Streaming):&lt;/span&gt;&lt;/h3&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;I use&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;#EXT-X-MEDIA&lt;/code&gt;&amp;nbsp;tags within the main manifest to declare separate audio tracks and subtitles, linking them to their own small manifests or files.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Original HLS Manifest (Video Only — Simplified):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Integrated HLS Manifest (Video + Multiple Audio + Subtitles):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;span class="oc ld fs ns b bg od oe l of og"&gt;&lt;/span&gt;&lt;/pre&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="text-align: center;"&gt;&lt;em class="my"&gt;(Note: The&amp;nbsp;&lt;/em&gt;&lt;code class="da np nq nr ns b"&gt;&lt;em class="my"&gt;URI&lt;/em&gt;&lt;/code&gt;&lt;em class="my"&gt;&amp;nbsp;points to separate HLS manifests containing only the audio or subtitle segments)&lt;/em&gt;&lt;/p&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;strong class="mc ft"&gt;&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-weight: normal;"&gt;&lt;span class="mc ft"&gt;For DASH (Dynamic Adaptive Streaming over HTTP):&lt;/span&gt;&lt;/h3&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;DASH uses&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;&amp;lt;AdaptationSet&amp;gt;&lt;/code&gt;&amp;nbsp;elements within the MPD (Media Presentation Description) file. We simply add new&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;AdaptationSet&lt;/code&gt;&amp;nbsp;blocks for each audio language and subtitle file.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Original DASH Manifest (Video Only — Simplified):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;/pre&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;(Simplified) Integrated DASH Manifest (Video + Audio + Subtitles):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;/pre&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="text-align: center;"&gt;&lt;em class="my"&gt;(Note: The&amp;nbsp;&lt;/em&gt;&lt;code class="da np nq nr ns b"&gt;&lt;em class="my"&gt;BaseURL&lt;/em&gt;&lt;/code&gt;&lt;em class="my"&gt;&amp;nbsp;points directly to the segmented audio file or the complete subtitle file)&lt;/em&gt;&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Payoff: Real-World Wins&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;This isn’t just theoretical. Implementing dynamic integration yielded dramatic results:&lt;/p&gt; 
      &lt;ul class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Slash Storage Costs:&lt;/strong&gt;&amp;nbsp;I achieved&amp;nbsp;&lt;strong class="mc ft"&gt;over 90% reduction&lt;/strong&gt;&amp;nbsp;in storage costs for multilingual content compared to duplicating video files. For a 1-hour video, adding 10 languages traditionally could mean +36GB; My way adds only about +1GB. That’s a&amp;nbsp;&lt;strong class="mc ft"&gt;72% saving&lt;/strong&gt;&amp;nbsp;just for the audio!&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Lightning-Fast Updates:&lt;/strong&gt;&amp;nbsp;Adding new languages to a&amp;nbsp;&lt;strong class="mc ft"&gt;5,000-asset library took under 2 hours&lt;/strong&gt;, compared to an estimated 2&amp;nbsp;&lt;em class="my"&gt;weeks&lt;/em&gt;&amp;nbsp;using traditional re-encoding methods. Integrating just the new audio/subtitle tracks often takes&amp;nbsp;&lt;strong class="mc ft"&gt;less than 5 minutes&lt;/strong&gt;&amp;nbsp;per asset.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Simplified Operations:&lt;/strong&gt;&amp;nbsp;Language management is decoupled from video assets. Adding or removing languages becomes a simple manifest update, not a complex re-processing job. Troubleshooting is easier too.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Better User Experience:&lt;/strong&gt;&amp;nbsp;Viewers get the same high-quality video regardless of language choice, full control over language selection, and improved accessibility compliance.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;blockquote class="nm nn no"&gt; 
       &lt;p class="ma mb my mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;&lt;em class="fs"&gt;“90% storage savings and updates in hours, not weeks? That’s the power of dynamic manifest integration.”&lt;/em&gt;&lt;/p&gt; 
      &lt;/blockquote&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;Tackling the Technical Hurdles&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;Of course, it wasn’t entirely straightforward. Key challenges included:&lt;/p&gt; 
      &lt;ol class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Path Resolution:&lt;/strong&gt;&amp;nbsp;Ensuring the manifest correctly points to audio/subtitle files, especially if they live in different storage locations than the video (e.g., calculating relative paths like&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;../audio/ENG.m3u8&lt;/code&gt;&amp;nbsp;correctly).&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Language Tagging:&lt;/strong&gt;&amp;nbsp;Using consistent language codes (like ISO 639) and setting appropriate defaults for a smooth user experience.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Synchronization:&lt;/strong&gt;&amp;nbsp;Making sure audio and subtitles align perfectly with the video requires matching segment durations and timestamps precisely.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;CDN Caching:&lt;/strong&gt;&amp;nbsp;Ensuring Content Delivery Networks (CDNs) pick up the updated manifests quickly after changes are made.&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;Careful implementation addressing these points is crucial for robust playback.&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;Conclusion: Work Smarter, Not Harder for Global Reach&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;Dynamic integration of audio and subtitles isn’t just a neat technical trick; it’s a fundamental shift in how we approach multilingual content delivery. By intelligently using the capabilities already built into HLS and DASH, we can bypass the costly and time-consuming process of re-encoding.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;This approach directly translates technical efficiency into business agility. It allows streaming platforms to:&lt;/p&gt; 
      &lt;ul class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;Expand globally much faster and more affordably.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;Respond quickly to market demands for specific languages.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;Offer a better, more inclusive experience to viewers worldwide.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;For any platform serious about international scale, this dynamic manifest pattern offers a powerful alternative to traditional methods. It proves that sometimes, the most impactful innovation comes not from inventing new technologies, but from finding smarter, more efficient ways to use the standards we already have.&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97807"&gt; 
  &lt;div class="elementor-element elementor-element-287921be e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-71572e41 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Global Streaming Dream vs. The Costly Reality&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;In today’s hyper-connected world, streaming platforms dream of reaching global audiences. Viewers expect content in&amp;nbsp;&lt;em class="my"&gt;their&lt;/em&gt;&amp;nbsp;language, and delivering that is no longer a luxury — it’s a necessity. But ask any video engineer about adding multiple languages to a large content library, and you’ll likely hear a sigh. Why? Because the traditional methods are often a budget-draining nightmare.&lt;/span&gt;&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;As a video engineer, I faced this challenge head-on. Expanding content globally meant dealing with the harsh reality of multiplying infrastructure costs.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Old Way: Expensive, Slow, and Inefficient&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;Traditionally, adding a new audio track or subtitle set meant going back to square one:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Re-encoding:&lt;/strong&gt;&amp;nbsp;Processing the&amp;nbsp;&lt;em class="my"&gt;entire&lt;/em&gt;&amp;nbsp;video file again for&amp;nbsp;&lt;em class="my"&gt;each&lt;/em&gt;&amp;nbsp;new language.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Duplication:&lt;/strong&gt;&amp;nbsp;Generating and storing complete, separate sets of video segments for every language variant.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Storage Bloat:&lt;/strong&gt;&amp;nbsp;Paying to store visually identical video content over and over.&lt;/span&gt;&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Manifest Mayhem:&lt;/strong&gt;&amp;nbsp;Juggling complex sets of separate manifest files for each version.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;Imagine doing this for thousands of assets and ten different languages. The costs (storage, processing) and time commitment scale frighteningly fast, becoming a major bottleneck to global expansion.&lt;/span&gt;&lt;/p&gt; 
      &lt;blockquote class="nm nn no"&gt; 
       &lt;p class="ma mb my mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;em class="fs"&gt;“Adding languages traditionally meant re-encoding everything. For large libraries, costs spiraled out of control.”&lt;/em&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;/blockquote&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;A Smarter Approach: Dynamic Manifest Integration&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;I knew there had to be a better way. Instead of brute-forcing the problem, I looked at the elegance of modern streaming protocols like HLS and DASH. My solution leverages their flexibility through&amp;nbsp;&lt;strong class="mc ft"&gt;Dynamic Manifest Integration&lt;/strong&gt;.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;Think of a streaming manifest (like an HLS&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;.m3u8&lt;/code&gt;&amp;nbsp;or a DASH&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;.mpd&lt;/code&gt;&amp;nbsp;file) as a detailed “playlist” or “table of contents” that tells the video player exactly where to find the video, audio, and subtitle segments it needs to play.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;My approach cleverly modifies this playlist:&lt;/p&gt; 
      &lt;ol class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Keep One Video:&lt;/strong&gt;&amp;nbsp;I maintain just&amp;nbsp;&lt;em class="my"&gt;one&lt;/em&gt;&amp;nbsp;high-quality set of video segments. No visual duplication!&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Separate Audio/Subtitles:&lt;/strong&gt;&amp;nbsp;Audio tracks and subtitle files are processed and stored independently.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Update the Playlist:&lt;/strong&gt;&amp;nbsp;I dynamically update the&amp;nbsp;&lt;em class="my"&gt;manifest file&lt;/em&gt;&amp;nbsp;to simply&amp;nbsp;&lt;em class="my"&gt;point&lt;/em&gt;&amp;nbsp;to these external audio and subtitle components.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Seamless Experience:&lt;/strong&gt;&amp;nbsp;The player reads the updated manifest, presents the user with all available language options, and plays the correct combination using the&amp;nbsp;&lt;em class="my"&gt;same&lt;/em&gt;&amp;nbsp;video stream.&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;How It Works: A Peek Under the Hood (HLS &amp;amp; DASH)&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk"&gt;The magic lies in specific tags within the manifest files.&lt;/p&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;strong class="mc ft"&gt;&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-weight: normal;"&gt;&lt;span class="mc ft"&gt;For HLS (HTTP Live Streaming):&lt;/span&gt;&lt;/h3&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;I use&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;#EXT-X-MEDIA&lt;/code&gt;&amp;nbsp;tags within the main manifest to declare separate audio tracks and subtitles, linking them to their own small manifests or files.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Original HLS Manifest (Video Only — Simplified):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;&lt;img class="aligncenter wp-image-7089 size-full" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/code_20250420_170306_via_10015_io-Dec-15-2025-11-12-59-3769-AM.png?width=1304&amp;amp;height=438&amp;amp;name=code_20250420_170306_via_10015_io-Dec-15-2025-11-12-59-3769-AM.png" alt="" width="1304" height="438"&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Integrated HLS Manifest (Video + Multiple Audio + Subtitles):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;span class="oc ld fs ns b bg od oe l of og"&gt;&lt;img class="aligncenter wp-image-7091 size-full" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/code_20250420_171029_via_10015_io-Dec-15-2025-11-13-05-6826-AM.png?width=2344&amp;amp;height=1062&amp;amp;name=code_20250420_171029_via_10015_io-Dec-15-2025-11-13-05-6826-AM.png" alt="" width="2344" height="1062"&gt;&lt;/span&gt;&lt;/pre&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="text-align: center;"&gt;&lt;em class="my"&gt;(Note: The&amp;nbsp;&lt;/em&gt;&lt;code class="da np nq nr ns b"&gt;&lt;em class="my"&gt;URI&lt;/em&gt;&lt;/code&gt;&lt;em class="my"&gt;&amp;nbsp;points to separate HLS manifests containing only the audio or subtitle segments)&lt;/em&gt;&lt;/p&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;strong class="mc ft"&gt;&amp;nbsp;&lt;/strong&gt;&lt;/h3&gt; 
      &lt;h3 class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-weight: normal;"&gt;&lt;span class="mc ft"&gt;For DASH (Dynamic Adaptive Streaming over HTTP):&lt;/span&gt;&lt;/h3&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk"&gt;&lt;span style="font-size: 16px;"&gt;DASH uses&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;&amp;lt;AdaptationSet&amp;gt;&lt;/code&gt;&amp;nbsp;elements within the MPD (Media Presentation Description) file. We simply add new&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;AdaptationSet&lt;/code&gt;&amp;nbsp;blocks for each audio language and subtitle file.&lt;/span&gt;&lt;/p&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;Original DASH Manifest (Video Only — Simplified):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;img class="aligncenter wp-image-7092 size-full" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/code_20250420_171535_via_10015_io-Dec-15-2025-11-13-04-5910-AM.png?width=1112&amp;amp;height=918&amp;amp;name=code_20250420_171535_via_10015_io-Dec-15-2025-11-13-04-5910-AM.png" alt="" width="1112" height="918"&gt;&lt;/pre&gt; 
      &lt;ul class=""&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong class="mc ft"&gt;(Simplified) Integrated DASH Manifest (Video + Audio + Subtitles):&lt;/strong&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;pre class="nu nv nw nx ny nz ns oa bp ob bb bk"&gt;&lt;img class="aligncenter size-full wp-image-7093" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/code_20250420_171611_via_10015_io-Dec-15-2025-11-13-00-5229-AM.png?width=1246&amp;amp;height=3078&amp;amp;name=code_20250420_171611_via_10015_io-Dec-15-2025-11-13-00-5229-AM.png" alt="" width="1246" height="3078"&gt;&lt;/pre&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="text-align: center;"&gt;&lt;em class="my"&gt;(Note: The&amp;nbsp;&lt;/em&gt;&lt;code class="da np nq nr ns b"&gt;&lt;em class="my"&gt;BaseURL&lt;/em&gt;&lt;/code&gt;&lt;em class="my"&gt;&amp;nbsp;points directly to the segmented audio file or the complete subtitle file)&lt;/em&gt;&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;The Payoff: Real-World Wins&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;This isn’t just theoretical. Implementing dynamic integration yielded dramatic results:&lt;/p&gt; 
      &lt;ul class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Slash Storage Costs:&lt;/strong&gt;&amp;nbsp;I achieved&amp;nbsp;&lt;strong class="mc ft"&gt;over 90% reduction&lt;/strong&gt;&amp;nbsp;in storage costs for multilingual content compared to duplicating video files. For a 1-hour video, adding 10 languages traditionally could mean +36GB; My way adds only about +1GB. That’s a&amp;nbsp;&lt;strong class="mc ft"&gt;72% saving&lt;/strong&gt;&amp;nbsp;just for the audio!&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Lightning-Fast Updates:&lt;/strong&gt;&amp;nbsp;Adding new languages to a&amp;nbsp;&lt;strong class="mc ft"&gt;5,000-asset library took under 2 hours&lt;/strong&gt;, compared to an estimated 2&amp;nbsp;&lt;em class="my"&gt;weeks&lt;/em&gt;&amp;nbsp;using traditional re-encoding methods. Integrating just the new audio/subtitle tracks often takes&amp;nbsp;&lt;strong class="mc ft"&gt;less than 5 minutes&lt;/strong&gt;&amp;nbsp;per asset.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Simplified Operations:&lt;/strong&gt;&amp;nbsp;Language management is decoupled from video assets. Adding or removing languages becomes a simple manifest update, not a complex re-processing job. Troubleshooting is easier too.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;&lt;strong class="mc ft"&gt;Better User Experience:&lt;/strong&gt;&amp;nbsp;Viewers get the same high-quality video regardless of language choice, full control over language selection, and improved accessibility compliance.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;blockquote class="nm nn no"&gt; 
       &lt;p class="ma mb my mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;&lt;em class="fs"&gt;“90% storage savings and updates in hours, not weeks? That’s the power of dynamic manifest integration.”&lt;/em&gt;&lt;/p&gt; 
      &lt;/blockquote&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;Tackling the Technical Hurdles&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;Of course, it wasn’t entirely straightforward. Key challenges included:&lt;/p&gt; 
      &lt;ol class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Path Resolution:&lt;/strong&gt;&amp;nbsp;Ensuring the manifest correctly points to audio/subtitle files, especially if they live in different storage locations than the video (e.g., calculating relative paths like&amp;nbsp;&lt;code class="da np nq nr ns b"&gt;../audio/ENG.m3u8&lt;/code&gt;&amp;nbsp;correctly).&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Language Tagging:&lt;/strong&gt;&amp;nbsp;Using consistent language codes (like ISO 639) and setting appropriate defaults for a smooth user experience.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;Synchronization:&lt;/strong&gt;&amp;nbsp;Making sure audio and subtitles align perfectly with the video requires matching segment durations and timestamps precisely.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx ne nf ng bk"&gt;&lt;strong class="mc ft"&gt;CDN Caching:&lt;/strong&gt;&amp;nbsp;Ensuring Content Delivery Networks (CDNs) pick up the updated manifests quickly after changes are made.&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;Careful implementation addressing these points is crucial for robust playback.&lt;/p&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2 class="lc ld fs bf le lf lg lh li lj lk ll lm ln lo lp lq lr ls lt lu lv lw lx ly lz bk"&gt;Conclusion: Work Smarter, Not Harder for Global Reach&lt;/h2&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md me mf mg mh mi mj mk ml mm mn mo mp mq mr ms mt mu mv mw mx fl bk" style="font-size: 16px;"&gt;Dynamic integration of audio and subtitles isn’t just a neat technical trick; it’s a fundamental shift in how we approach multilingual content delivery. By intelligently using the capabilities already built into HLS and DASH, we can bypass the costly and time-consuming process of re-encoding.&lt;/p&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;This approach directly translates technical efficiency into business agility. It allows streaming platforms to:&lt;/p&gt; 
      &lt;ul class="" style="font-size: 16px;"&gt; 
       &lt;li class="ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx nt nf ng bk"&gt;Expand globally much faster and more affordably.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;Respond quickly to market demands for specific languages.&lt;/li&gt; 
       &lt;li class="ma mb fs mc b md nh mf mg mh ni mj mk ml nj mn mo mp nk mr ms mt nl mv mw mx nt nf ng bk"&gt;Offer a better, more inclusive experience to viewers worldwide.&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p class="pw-post-body-paragraph ma mb fs mc b md mz mf mg mh na mj mk ml nb mn mo mp nc mr ms mt nd mv mw mx fl bk" style="font-size: 16px;"&gt;For any platform serious about international scale, this dynamic manifest pattern offers a powerful alternative to traditional methods. It proves that sometimes, the most impactful innovation comes not from inventing new technologies, but from finding smarter, more efficient ways to use the standards we already have.&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fthe-smart-way-to-add-languages-to-your-streaming-content-without-breaking-the-bank%2Ftermtech&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <pubDate>Mon, 23 Jun 2025 18:15:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/the-smart-way-to-add-languages-to-your-streaming-content-without-breaking-the-bank/termtech</guid>
      <dc:date>2025-06-23T18:15:00Z</dc:date>
      <dc:creator>Mostaq Ahmed Polok</dc:creator>
    </item>
    <item>
      <title>AWS Lambda integration testing with Python, Localstack, and Terraform</title>
      <link>https://www.craftsmensoftware.com/blog/private-aws-lambda-integration-testing-with-python-localstack-and-terraform</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/private-aws-lambda-integration-testing-with-python-localstack-and-terraform" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/AWS-Lambda-Integration-Testing-With-Python-Localstack-And-Terraform.webp" alt="AWS Lambda integration testing with Python, Localstack, and Terraform" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;p&gt;To start with unit testing for AWS Lambda integration testing with Python, Localstack, and Terraform we can just choose a testing framework and start writing our beautiful unit tests. For testing AWS services we also can use some mock tools like moto. But what about integration testing? A solution may be to deploy with the Continuous Deployment tool and run some test code against real AWS services. But there are some problems:&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;To start with unit testing for AWS Lambda integration testing with Python, Localstack, and Terraform we can just choose a testing framework and start writing our beautiful unit tests. For testing AWS services we also can use some mock tools like moto. But what about integration testing? A solution may be to deploy with the Continuous Deployment tool and run some test code against real AWS services. But there are some problems:&lt;/p&gt;  
&lt;ul&gt; 
 &lt;li&gt; &lt;p&gt;It takes more time to deploy every time&lt;/p&gt; &lt;/li&gt; 
 &lt;li&gt; &lt;p&gt;Running test code against AWS takes more time&lt;/p&gt; &lt;/li&gt; 
 &lt;li&gt; &lt;p&gt;Increases the AWS bills&lt;/p&gt; &lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;So one good solution could be using a local infrastructure that resembles the same as AWS real infrastructure. So here comes our friend Localstack to solve the problem. And today we will take a look at how we can use Localstack for integration testing of AWS Lambda.&lt;br&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h3&gt;Prerequisite&lt;/h3&gt; 
&lt;ul&gt; 
 &lt;li&gt; &lt;p&gt;Python for lambda and test code&lt;/p&gt; &lt;/li&gt; 
 &lt;li&gt; &lt;p&gt;Terraform, an IaC tool to deploy lambda at the Localstack&lt;/p&gt; &lt;/li&gt; 
 &lt;li&gt; &lt;p&gt;Localstack to use AWS infrastructure locally&lt;/p&gt; &lt;/li&gt; 
 &lt;li&gt; &lt;p&gt;Docker, latest Localstack version needs docker to run.&lt;/p&gt; &lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;Install python version greater than on equal 3.8, Terraform version 1.10.2 and latest docker.&lt;br&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h3&gt;The Skeleton&lt;/h3&gt; 
&lt;p&gt;Install terraform version 1.8.2 from here on your local machine.&lt;br&gt;&lt;br&gt;1. Create project directory&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;2. Create directory for lambda codes&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;3. Add handler.py file in lambda directory&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;4. Create directory for terraform&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;5. Add requirements file in project root directory&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;6. Create directory for test code&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;7. Create python file for test code&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;8. So the skeleton will look like this&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Add requirements&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;span&gt;Let’s add some python requirements in &lt;strong&gt;requirements.txt &lt;/strong&gt;file&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Make a python virtual environment named “venv”&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Activate virtual environment and install necessary packages from requirements.txt file&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Add Lambda Code&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;span&gt;We will add a very simple code. Our lambda will just get the webpage &lt;/span&gt;&lt;a href="https://example.com/" style="color: #1ebbf0;"&gt;&lt;span&gt;https://example.com&lt;/span&gt;&lt;/a&gt;&lt;span&gt; and return the page source as text.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Add Files to deploy Lambda&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;span&gt;Let’s add a terraform variable for the lambda function name. So from our test code, we will provide the lambda function name and then test it to make the testing more dynamic. Add a file &lt;code&gt;vars.tf&lt;/code&gt; in &lt;code&gt;terraform&lt;/code&gt; dir and add following codes.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Now add terraform code for lambda at `&lt;/span&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;terraform/lambda.tf` &lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Now we are going to add &lt;/span&gt;&lt;strong&gt;&lt;strong style="color: #1d202b; background-color: #ffffff;"&gt;terraform/localstack.tf&lt;/strong&gt;&lt;/strong&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt; &lt;/span&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;to which will tell terraform to use Localstack for deployment&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Deploy to Localstack with Terraform&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;span&gt;Now time to test deployment at LocalStack&lt;/span&gt;&lt;/p&gt; 
&lt;ol style="list-style-type: decimal; color: #1d202b; background-color: #ffffff;"&gt; 
 &lt;li&gt;Run command to start localstack in one terminal window&lt;/li&gt; 
&lt;/ol&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;2. On another terminal run commands to test deployment. But this is only for testing and we are going to automate it in next steps.&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Automate Test Code&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;span&gt;Now time to automate the lambda testing. Our strategy:&lt;/span&gt;&lt;/p&gt; 
&lt;ul style="list-style-type: disc; color: #1d202b; background-color: #ffffff;"&gt; 
 &lt;li&gt;&lt;span&gt;Deploy terraform to LocalStack from test code e.g python code&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;Execute lambda using boto3&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;Check if we get the webpage as text&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;Destroy infrastructure with terraform to LocalStack using test code&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;ol style="list-style-type: decimal; color: #1d202b; background-color: #ffffff;"&gt; 
 &lt;li&gt;&lt;span&gt;Add terraform helper function at &lt;/span&gt;&lt;strong&gt;tests/terraform_helper.py&lt;/strong&gt;&lt;span&gt; which will responsible for creating infrastructure at test start and destroy after the test&lt;/span&gt;&lt;/li&gt; 
&lt;/ol&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Let’s add test code and we are going to use python’s unit test module to test our code&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;Finally, the project will look like this&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Time to test the Test&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;Now come to the moment of playing &#x1f3bb;&lt;/p&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;As we implemented the tests with the unit test module, we can run the test using&lt;/p&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;span style="color: #1d202b; background-color: #ffffff;"&gt;After a lot of logs we can see final output like this&lt;/span&gt;&amp;nbsp;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;⚠️ WARNING&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;Localstack is growing very faster. So if it works today may break tomorrow if the required packages are not fixed. So please try to fix all the packages version in Pipfile. Sometimes it may require some python packages to start various services like DynamoDB or StepFuntions. Add those at Pipfile accordingly.&lt;/p&gt; 
&lt;h2 style="color: #333333; line-height: 33.6px; background-color: #ffffff;"&gt;Final codes&lt;/h2&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;All of the codes are in this GitHub repository:&lt;/p&gt; 
&lt;p style="color: #1d202b; background-color: #ffffff;"&gt;&lt;a href="https://github.com/melon-ruet/lambda-testing-localstack" style="color: #1ebbf0;"&gt;https://github.com/melon-ruet/lambda-testing-localstack&lt;/a&gt;&lt;/p&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fprivate-aws-lambda-integration-testing-with-python-localstack-and-terraform&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <pubDate>Tue, 15 Apr 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/private-aws-lambda-integration-testing-with-python-localstack-and-terraform</guid>
      <dc:date>2025-04-15T18:00:00Z</dc:date>
      <dc:creator>Mahabubur Rahaman Melon</dc:creator>
    </item>
    <item>
      <title>Mastering Sorting Techniques in DynamoDB: From Chaos to Clarity - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/mastering-sorting-techniques-in-dynamodb-from-chaos-to-clarity</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/mastering-sorting-techniques-in-dynamodb-from-chaos-to-clarity" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/Mastering-Sorting-Techniques-in-DynamoDB-From-Chaos-to-Clarity.png" alt="Mastering Sorting Techniques in DynamoDB: From Chaos to Clarity - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96876"&gt; 
  &lt;div class="elementor-element elementor-element-7c69b395 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-629d03d0 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;span style="font-size: 18px;"&gt;&lt;span style="font-size: 16px;"&gt;Amazon DynamoDB is a highly efficient, scalable, and low-latency NoSQL database service, ideal for managing large data volumes and high traffic loads.&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96876"&gt; 
  &lt;div class="elementor-element elementor-element-7c69b395 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-629d03d0 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;span style="font-size: 18px;"&gt;&lt;span style="font-size: 16px;"&gt;Amazon DynamoDB is a highly efficient, scalable, and low-latency NoSQL database service, ideal for managing large data volumes and high traffic loads.&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size: 16px;"&gt;Its robust architecture and single table design principle ensure exceptional performance and reliability which makes DynamoDB a top choice for &lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;numerous applications.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;With great power comes great responsibility, hence one of the key challenges developers often experience while working with DynamoDB is implementing efficient sorting strategies, which can have a major effect on how well data is retrieved.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 18px;"&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt;In this blog I will cover fundamental principles, advanced mechanism, and practical advice for turning chaotic data into orderly resources.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Sort Key in DynamoDB:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB supports two kinds of primary keys: the partition key and the composite primary key. A partition key(aka hash key) is a single attribute, while a composite primary key includes a combination of 2 attributes: ‘hash key’ and ‘sort key’.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB uses the partition key value as input to the hash function. The output from the hashing function determines which partition the item will be placed in. A sort key is also referred to as a range attribute of an item and used to arrange and organize items in a partition. It is possible that many items will have the same value for a partition key; however, they must have different values for sort keys.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;By default the Items in DynamoDB partitions are ordered by sort key in ascending order. A well defined sort key provides the capability to query dynamoDB tables by using the conditions expression.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The Sort key cannot be changed after table provisioning, Therefore be mindful when creating a sort key. If your data contains hierarchical (one-to-many) relationships and you want to query at any hierarchy level, use a composite primary key.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;For example, The sort key for a restaurant DDB table can be structured as follows.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-da260be elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt; 
        &lt;pre class="highlight-height  language-javascript"&gt;&amp;nbsp;&lt;/pre&gt; 
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-dfade90 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here ‘chain’ means company name of the restaurant.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here, the sort key allows for efficient range queries for locations at various levels of aggregation, from ‘chain’ to ‘area’, and everything in between. By defining sort key as above we can query table with more granularity, like if we want to get data for a specific ‘chain’ then we can query with sortkey &lt;/span&gt;&lt;strong&gt;begins_with &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;chain#&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; , similarly if we want to get data for any specific ‘country’ we can query the table like sortkey &lt;/span&gt;&lt;strong&gt;begins_with &lt;/strong&gt;&lt;i&gt;&lt;span style="font-weight: 400;"&gt;chain#country&lt;/span&gt;&lt;/i&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Points to consider for Sort Key:&lt;/h2&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;The sort key attribute must be a scaler type.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It should be noted that within a partition, sort key has to be unique meaning that there ought to be no other item with the same partition key as well as the same sort key.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Sort key names can’t be a reserved words. You can see the reserve list in the &lt;/span&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ReservedWords.html"&gt;&lt;span style="font-weight: 400;"&gt;dynamoDB documentation here&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;The length of the sort key attribute should not exceed 255 characters.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Sort keys should follow &lt;/span&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.NamingRules"&gt;&lt;span style="font-weight: 400;"&gt;DynamoDb’s naming conventions&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; for attributes.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Name your Sort Key Attribute something meaningful and descriptive that reflects the type of data it is holding so that when you make queries, they will make more sense and help in faster execution.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;&amp;nbsp;&lt;/h2&gt; 
      &lt;h2&gt;Diving Deeper: Sorting Mechanism in DynamoDB&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The most fundamental sorting strategy in DynamoDB involves using the sort key of your table’s primary key. If you define a composite primary key with partition key + sort key, DynamoDB will store items inside every partition automatically in ascending order of the sort key.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here are two main rules you will need to get into the habit of following if you need any kind of specific ordering when reading multiple items in DynamoDB.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;You’re going to have to use composite primary keys first.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Second, ordering must be done with the sort key of a certain item collection.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB uses the partition key to isolate item collections into different partitions. This then supports O(1) lookup time to find the proper node. Afterward, items inside an item collection are stored as a B-tree to allow O(log n) time complexity in search. This B-tree is arranged in lexicographical order according to the sort key and forms what is used for sorting.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In this blog I will delve into the following sorting mechanism:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Basics of sorting:&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ol&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ol&gt; 
         &lt;li style="list-style-type: none;"&gt; 
          &lt;ol&gt; 
           &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Lexicographical sorting mechanism.&lt;/span&gt;&lt;/li&gt; 
           &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Sorting with Timestamps, how to handle timestamps,&lt;/span&gt;&lt;/li&gt; 
           &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Unique, sortable IDs (unique identifiers that still need sorted chronologically).&lt;/span&gt;&lt;/li&gt; 
          &lt;/ol&gt; &lt;/li&gt; 
        &lt;/ol&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Sorting on changing attributes&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Ascending vs. Descending sorting&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Two relational access patterns in a single item collection&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Zero-padding with numbers&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul&gt; 
       &lt;li&gt;Faking ascending order&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s get started, there’s a lot to discuss!&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;1. Basics of sorting:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Sorting is done in DynamoDB only based on the sort key which can be a scalar types such as: string, number or binary. This implies that we do not need to consider how a map attribute will be sorted by DynamoDB.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In cases where sort keys are numbers, they are directly ordered according to their numerical values. However, for sort keys of type strings or binaries, items are arranged based on the order of UTF-8 bytes. Now let’s examine this more closely.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;1.1. Lexicographical sorting:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;A simplified version of sorting on UTF-8 bytes is to say the ordering is lexicographical. Lexicographical sorting, also known as dictionary or alphabetical order, It is the default method of sorting strings in DynamoDB. Strings are compared character by character in this method based on their Unicode values.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To determine what character comes after which, consider the sequence written below:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Symbols(e.g. # or $) and Numbers (0-9) come before uppercase letters.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Uppercase letters (A-Z) come before lowercase letters.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Lowercase letters (a-z) come last.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Notice that these letters are separated by case (first capital letters and afterwards lowercase). This means “Banana” will come before “apple”. That is crucial to be aware of if you want to avoid surprises later.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s an example table demonstrating the lexicographical ordering of various characters based on their UTF-8 values(dec):&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-f3bf78b elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image2-3.png?width=1024&amp;amp;height=768&amp;amp;name=image2-3.png" class="attachment-large size-large wp-image-96890" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-6eb8dcb elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;I’m &lt;/span&gt;&lt;a href="https://www.fileformat.info/info/charset/UTF-8/list.htm"&gt;&lt;span style="font-weight: 400;"&gt;refering to this page&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt; for a complete list of UTF-8 characters including special ones sorted according to their bytes order.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Example of a lexicographical sorting with Uppercase Rule:&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;A common mistake people make with lexicographical ordering is forgetting the uppercase rule. For instance, consider an item collection with names “Ellen VanDyke” (with a capital “D” in the middle of VanDyke), ‘Alice Vanbyke’ and ‘Bob Vanhoten’, In an item collection using these last names as SK. it might turn out as follows:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-180b9af elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image10-1.png?width=1024&amp;amp;height=768&amp;amp;name=image10-1.png" class="attachment-large size-large wp-image-96894" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-fe46e25 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You might be surprised to see that ‘VanDyke’ came before ‘Vanbyke’! This is due to the casing uppercase before lowercase. To avoid odd behavior around this, standardize your sort keys to either all uppercase or all lowercase values:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-06537c7 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image8-1.png?width=1024&amp;amp;height=768&amp;amp;name=image8-1.png" class="attachment-large size-large wp-image-96898" alt=""&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-8140dd6 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here, when all last names are in uppercase, they are sorted as expected.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;1.2. Sorting with Timestamps:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Regarding sorting, the second fundamental issue I want to mention is how to go about timestamps. First and foremost, your choice must be such that it can be sorted. What you definitely cannot do is use a non-sortable format like “May 26, 1988”. This will not sort in DynamoDB and you will have some painful moments there.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Personally, I prefer to use ISO 8601 format: “YYYY-MM-DDTHH:MM:SSZ”. Because this format is human-readable and it also follow lexicographical order.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This ISO 8601 format is universally recognized standard used in many countries across the globe for showing dates-times (e.g., “2023-05-15T10:30:00Z”). It consists of year, month, day, hour, minutes, seconds, and then Z suffix indicating UTC timezone.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Eg: “2023-07-10T14:48:00Z” which will properly sort before “2023-07-11T15:00:00Z”.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;1.2. Unique, sortable IDs:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;An often encountered requirement is to have unique IDs that can be sorted. This mostly comes where you need an item with a unique identifier (preferably URL friendly) but you still want them ordered by date or time created. In this arena, there are several options but ‘KSUID’ implementation stands out for me.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;KSUID means &lt;/span&gt;&lt;strong&gt;K&lt;/strong&gt; &lt;strong&gt;S&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;ortable &lt;/span&gt;&lt;strong&gt;U&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;nique &lt;/span&gt;&lt;strong&gt;I&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;dentifier. Simply, it’s an identification number that begins with a timestamp and has enough randomness to minimize the possibility of overlapping values. On the whole this gives you a 27-character string, which is better than any UUIDv4 but yet achieves lexicographical sortability.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;For more check out &lt;/span&gt;&lt;a href="https://segment.com/blog/a-brief-history-of-the-uuid/"&gt;&lt;span style="font-weight: 400;"&gt;Rick’s blog post on the implementation of KSUIDs&lt;/span&gt;&lt;/a&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;2. Sorting on changing attributes:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB uses the sort key to sort items within a collection, useful for displaying recently stored items or top scores. However, sorting based on frequently changing values can be challenging. For example, consider a ticket tracker app might allow users to view tickets in order by most recently updated.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s imagine you decide to model your table as follows:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-feb7c08 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image9-1.png?width=1024&amp;amp;height=768&amp;amp;name=image9-1.png" class="attachment-large size-large wp-image-96925" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-76f8209 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This database design uses the organization name as a partition key for ‘group by’ functionality and sorting tickets with the &lt;/span&gt;&lt;strong&gt;‘UpdatedAt’ &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;field as a sort key for order. However, this design has limitations, as the primary key cannot be changed during item modification. In your case, you have included &lt;/span&gt;&lt;strong&gt;‘UpdatedAt’ &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;field into the primary key which changes each time a ticket is updated. So whenever you update a ticket item, first delete the existing ticket item, and then create another new one with updated primary key. causing a complicated process and potential data loss if not handled properly.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;However, I’m thinking maybe we can do things differently here. For our primaryKey, let’s give two attributes that will not change anything at all. We’ll keep ‘OrganizationName’ as partition key but switch to using ‘TicketId’ as sort key instead.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;So, here is how our table looks like now.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-02a6c31 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image12-1.png?width=1024&amp;amp;height=768&amp;amp;name=image12-1.png" class="attachment-large size-large wp-image-96918" alt=""&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-a1021ad elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;At this point, we can also add local secondary index which has a secondary sort key known as &lt;/span&gt;&lt;strong&gt;‘UpdatedAt’&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. The information contained in the base table gets copied into the secondary index and appears as shown:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-0ef7f8e elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image6-2.png?width=1024&amp;amp;height=768&amp;amp;name=image6-2.png" class="attachment-large size-large wp-image-96929" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-27862c3 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Note that this was exactly how our original table design used to be. Consequently, we can use the Query API against this secondary index to satisfy our ‘Fetch most recently updated tickets’ access pattern. Significantly, there is no need for us to worry about complex delete + create logic while trying to update an item because DynamoDB takes care of all this when replicating data into secondary index.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;3. Ascending vs. Descending sorting:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;We know DynamoDB by default reads the items in &lt;/span&gt;&lt;strong&gt;&lt;i&gt;ascending &lt;/i&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;order. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;By employing ‘&lt;/span&gt;&lt;strong&gt;ScanIndexForward=False&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;’ you will be reading them in descending order. This is useful in many cases such as when you want the most recent timestamps or check highest score on a leaderboard.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;But it becomes complex if you combine different entity types into a single item collection and then try to read them back together with a parent object for establishing a one-to-many relationship between parent and child entities. In that situation you need to consider the common sort order you’ll use in this access pattern to know where to place the parent item.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;For example, let’s assume a library system where users often want to access a book with the latest 10 review items.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You could structure your table as shown below:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-4c488c5 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image5-1.png?width=1024&amp;amp;height=768&amp;amp;name=image5-1.png" class="attachment-large size-large wp-image-96936" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c6018d8 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here according to the table data our query retrieves the &lt;/span&gt;&lt;strong&gt;oldest &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Book and Review items, but if the collection is large, multiple pagination requests may be needed to fetch recent ones. To avoid this, you can prefix our Review items with ‘&lt;/span&gt;&lt;strong&gt;#&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;‘. After doing that, our table will appear as:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-b8a3d38 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image4-1.png?width=1024&amp;amp;height=768&amp;amp;name=image4-1.png" class="attachment-large size-large wp-image-96943" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-96ae071 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;So now if we use ‘&lt;/span&gt;&lt;strong&gt;ScanIndexForward=False&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;‘ our Query API will retrieve recent Review Items for each Book item starting from the last item in a collection.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;4. Two relational access patterns in a single item collection:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s take this example if we can have a one-to-many relationship where the related items are before or after the parent items, can we do both in one item collection?&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Yeah, sure! To achieve this you need to have two access patterns: one fetching related items in ascending order and another in descending order.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To give an illustration, consider a SaaS application where an organization has two sub-concepts: &lt;/span&gt;&lt;strong&gt;Employees &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;and &lt;/span&gt;&lt;strong&gt;Teams&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, each with a one-to-many relationship with the organization.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You could think of each of these relationships as having a relational access pattern ‘Fetch Organization and all {Employees|Teams} for the Organization’. Additionally, you would want Employees returned sorted by their names but not care how Teams are sorted because there shouldn’t be too many of them.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You could model your table as follows&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d703353 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image3-2.png?width=1024&amp;amp;height=768&amp;amp;name=image3-2.png" class="attachment-large size-large wp-image-96950" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-4dd0b1e elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This above table contains three types of items: Team, Org, and Employee. Each item has same &lt;/span&gt;&lt;strong&gt;PK &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;value of &lt;/span&gt;&lt;strong&gt;ORG#,&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; with Team items bearing &lt;/span&gt;&lt;strong&gt;SK #TEAM#&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, Org items bearing &lt;/span&gt;&lt;strong&gt;SK ORG#&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and Employee items bearing &lt;/span&gt;&lt;strong&gt;SK EMPLOYEE#&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. Here, the Org item is positioned between Team and Employee items, with the Team item preceding the Org item, The structure of our item collection was designed with a ‘#’ prefix, ensuring Team item precedes Org item.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Now we can query for all team items as well as org:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-4aea863 elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt; 
        &lt;pre class="highlight-height  language-javascript"&gt;&amp;nbsp;&lt;/pre&gt; 
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-b056e6a elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This process searches our partition, identify items less than or equal to the sort key value for our Org item, and then scans backward to retrieve all Team items.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Below is an image showing how it works on the table:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-4c9dfc6 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image11-1.png?width=1024&amp;amp;height=768&amp;amp;name=image11-1.png" class="attachment-large size-large wp-image-96966" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d8e6b81 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Alternatively you could do the reverse to fetch both Org item and Employee items, look for items greater than or equal to our Org item sort key and read forward to retrieve all Employee items from your table.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This is a very advanced pattern that doesn’t necessarily mean you must use it but it will eliminate more additional secondary indexes from your table.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;5. Zero-padding with numbers:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;One should be aware of lexicographic sorting with numbers represented as strings. For better demonstration. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;Let’s revisite&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; our above ‘Book Review’ example and now we are using &lt;/span&gt;&lt;strong&gt;‘RatingNumber’ &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;instead of timestamps for the sort key.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You can have a table that looks like this:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-dfac12f elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image7-1.png?width=1024&amp;amp;height=768&amp;amp;name=image7-1.png" class="attachment-large size-large wp-image-96979" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-1200aa3 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here, the rating order is incorrect, 10 is being placed before 2 due to lexicographic sorting. one character at a time is compared from the left towards right. When it compares ’10’ and ‘2’, the first digit(‘1’) in 10 comes before the first digit(‘2’) in 2, so 10 came before 2.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To avoid this, you can zero-pad your numbers—make sure that your sort key has a fixed length such as three digits in this case. When you find that your value does not contain many digits, you append with a ‘0’. Therefore, It will turn “10” into “010”, and “2” into “002”.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Now, this is how our table looks like:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-00e0afc elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image13-1.png?width=1024&amp;amp;height=768&amp;amp;name=image13-1.png" class="attachment-large size-large wp-image-96986" alt="DynamoDB sorting techniques"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c37e65b elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This means that RatingNumber 2 comes before RatingNumber 10 as expected. However, the main thing here involves you having the padding about to accommodate any increase. In this case, we had a fixed width of three digits thus reaching Rating number 999. Make your fixed length longer if your requirements are greater than that.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;6. Faking ascending order:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s revisite our above example of zero-padding with numbers&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. Now retrieve reviews in ascending order by the book name according to their rating, So here i am going to implement a technique to fake ascending order by transforming the sort key.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;We’ll modify the &lt;/span&gt;&lt;strong&gt;SK &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;into a FakeRating for efficient querying in ascending order. To fake ascending order, we can invert the ratings by subtracting each rating from a constant value (e.g., 100), then zero-pad the result to ensure lexicographical sorting,&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;That means, FakeRating = (100 – ActualRating) and then convert it to a zero-padded string.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;For example, imagine we were again using a zero-padded number with a width of 3. If we had an item with an ratingID of “10”, the zeropadded number would be “010”. To find the zero-padded difference, we subtract our number (“10”) from the highest possible value (“999”). Thus, the zero-padded difference would be “989”&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;If we put this in our table and query with ‘ScanIndexForward=False’ you would ge&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;t:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-f48c271 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="768" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image1-3.png?width=1024&amp;amp;height=768&amp;amp;name=image1-3.png" class="attachment-large size-large wp-image-96996" alt=""&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-382689c elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This strategy may appear unconventional and may not be necessary in practice. The most important lesson to learn from this approach is how versatile DynamoDB can be if you combine multiple strategies. Once you grasp the basics, you may put them together in unique ways to solve your problem.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;h2&gt;Conclusion:&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;When dealing with data management in DynamoDB, sorting is one of the core functions that decides how fast information can be retrieved. By understanding these above discussed sorting mechanism will help you optimize your DynamoDB tables for many difficult use cases so that you can maintain correct order and clearness in your data.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;From basic lexicographic ordering to advanced mechanism like zero-padding and faking ascending order, acquiring expertise in them will help you take advantage all the potentialities of DynamoDB. As your data grows and application scales, these sorting techniques will ensure your queries remain fast and efficient, keeping your data access organized and performant.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fmastering-sorting-techniques-in-dynamodb-from-chaos-to-clarity&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <category>DynamoDB</category>
      <pubDate>Wed, 09 Apr 2025 18:15:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/mastering-sorting-techniques-in-dynamodb-from-chaos-to-clarity</guid>
      <dc:date>2025-04-09T18:15:00Z</dc:date>
      <dc:creator>Shahed Chy Suzan</dc:creator>
    </item>
    <item>
      <title>Thinking in React: Component-Based Architecture</title>
      <link>https://www.craftsmensoftware.com/blog/thinking-in-react-component-based-architecture</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/thinking-in-react-component-based-architecture" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Thinking-in-React-Component-Based-Architecture.webp" alt="Thinking in React: Component-Based Architecture" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;p&gt;&lt;span&gt;React has revolutionized web development by giving developers a powerful tool for creating dynamic, responsive user experiences. The founding principle of React is its component-based architecture, which divides complicated user interfaces into smaller, reusable parts known as components. This simplifies code maintenance and reading, as well as helps in the development of scalable systems. In this blog, we will look at component-based architecture ideas and demonstrate how to apply them to the development of a React application.&lt;/span&gt;&lt;/p&gt;</description>
      <content:encoded>&lt;p&gt;&lt;span&gt;React has revolutionized web development by giving developers a powerful tool for creating dynamic, responsive user experiences. The founding principle of React is its component-based architecture, which divides complicated user interfaces into smaller, reusable parts known as components. This simplifies code maintenance and reading, as well as helps in the development of scalable systems. In this blog, we will look at component-based architecture ideas and demonstrate how to apply them to the development of a React application.&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;What is Component-Based Architecture?&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;A component-based architecture is an approach rather than a technique for developing UI whereby the UI is built by splitting it into reusable fragments called components. Each component is assigned to handle a particular feature or part of the user interface thus making the application easier to maintain and extend. The main ideas behind this architecture are:&lt;/span&gt;&lt;/p&gt; 
&lt;ol&gt; 
 &lt;li&gt;&lt;span&gt;Reusability: Components can be utilized in numerous places across the application, which helps to avoid writing the same code numerous times. For example, a button component designed for a form can be utilized in a pop-up or another portion of the app.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;Encapsulation: Components handle their own state and behavior, which enhances modularity. Each component has a clear interface and can be built, tested, and maintained independently.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;Separation of Concerns: Each component concentrates on a single task or function, which leads to cleaner and more manageable code. This separation enables developers to understand and work on each component of the application independently.&lt;/span&gt;&lt;/li&gt; 
&lt;/ol&gt; 
&lt;h2&gt;&lt;span&gt;Benefits of Component-Based Architecture&lt;/span&gt;&lt;/h2&gt; 
&lt;p style="font-weight: bold;"&gt;Improved Code Maintainability&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;Smaller, self-contained components are easier to manage and update.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;When a bug is found or a new feature is needed, developers can easily find and fix the specific component without searching through a lot of code.&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p style="font-weight: bold;"&gt;Enhanced Collaboration&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;Teams can work on different components at the same time without causing conflicts.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;This speeds up the overall project timeline and makes better use of team resources.&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p style="font-weight: bold;"&gt;Scalability&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;Adding new features or changing existing ones is simpler with a modular component structure.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;As the application grows, developers can build new components or change existing ones without affecting other parts of the application.&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;div style="overflow-x: auto; max-width: 100%; width: 89%; margin-left: auto; margin-right: auto;"&gt; 
 &lt;table style="width: 100%; border-collapse: collapse; table-layout: fixed; border: 1px solid #99acc2; height: 931px;"&gt; 
  &lt;tbody&gt; 
   &lt;tr style="height: 81.8906px;"&gt; 
    &lt;td style="width: 22.2401%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Aspect&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Traditional Monolithic Architecture&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Component-Based Architecture&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
   &lt;tr style="height: 106.188px;"&gt; 
    &lt;td style="width: 22.2401%; padding: 4px; height: 106.188px;"&gt;&lt;span&gt;Codebase&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 106.188px;"&gt;&lt;span&gt;One large, unified codebase&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 106.188px;"&gt;&lt;span&gt;Broken down into smaller, independent components&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
   &lt;tr style="height: 154.781px;"&gt; 
    &lt;td style="width: 22.2401%; padding: 4px; height: 154.781px;"&gt;&lt;span&gt;Scalability&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 154.781px;"&gt;&lt;span&gt;Difficult to manage and scale as the application grows&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 154.781px;"&gt;&lt;span&gt;Easier to scale by adding or modifying individual components&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
   &lt;tr style="height: 57.5938px;"&gt; 
    &lt;td style="width: 22.2401%; padding: 4px; height: 57.5938px;"&gt;&lt;span&gt;Impact of Changes&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 57.5938px;"&gt;&lt;span&gt;Changes in the UI can affect the entire application&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 57.5938px;"&gt;&lt;span&gt;Changes in one component typically don’t impact others&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
   &lt;tr style="height: 81.8906px;"&gt; 
    &lt;td style="width: 22.2401%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Development Efficiency&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Slower, as changes require careful consideration of the entire system&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 81.8906px;"&gt;&lt;span&gt;Faster, as developers can work on isolated components&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
   &lt;tr style="height: 57.5938px;"&gt; 
    &lt;td style="width: 22.2401%; padding-top: 4px; padding-right: 4px; padding-bottom: 4px; height: 57.5938px;"&gt;&lt;span&gt;Risk of Bugs&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 37.9056%; padding: 4px; height: 57.5938px;"&gt;&lt;span&gt;Higher risk, as changes in one area can cause bugs in another&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
    &lt;td style="width: 39.8459%; padding: 4px; height: 57.5938px;"&gt;&lt;span&gt;Lower risk, as components are independent and self-contained&lt;/span&gt;&amp;nbsp;&lt;/td&gt; 
   &lt;/tr&gt; 
  &lt;/tbody&gt; 
 &lt;/table&gt; 
&lt;/div&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;div&gt;
 &amp;nbsp;
&lt;/div&gt; 
&lt;h2&gt;&lt;span&gt;Core Concepts of React Components&lt;/span&gt;&lt;/h2&gt; 
&lt;p style="font-weight: bold;"&gt;Understanding Components and Props&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Components are the building blocks of a React application. Consider them as JavaScript functions that return HTML. Props (short for properties) are used to transfer data from one component to another, enabling dynamic content rendering.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;An example of a basic functioning component with props:&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;&lt;br&gt;State and Lifecycle&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;React comes with a built-in object called State that lets components handle their own data. To keep the user interface (UI) up to date with the data, state changes cause re-renders.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;Example of a component with state:&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Creating a React Application&lt;/span&gt;&lt;/h2&gt; 
&lt;p style="font-weight: bold;"&gt;Prerequisites&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Before building a React application, ensure you have the following:&lt;/span&gt;&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;&lt;strong&gt;Node.js &amp;amp; npm&lt;/strong&gt; installed on your system. You can check by running:&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;Basic understanding of JavaScript and ES6+ features &amp;amp; familiarity with React components (covered in the previous section).&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;&lt;span&gt;Once you have these in place, you’re ready to go.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;Setting up a React Project&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Use Create React App to start a new React app:&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;&lt;br&gt;Structuring the Project&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Configure your project using a well-defined folder structure:&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Building a Todo List Application&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;Creating and Organizing Components&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;In this section, we will develop a simple Todo List application, which will include three key components:&lt;/span&gt;&lt;span style="white-space-collapse: preserve;"&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;TodoItem: Represents an individual todo item.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;TodoList: Displays a list of todo items.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;TodoForm: Contains a form to add new todo items.&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;&lt;span&gt;&lt;span style="font-weight: bold;"&gt;TodoItem Component:&lt;/span&gt; The TodoItem component will receive a todo object as a prop and display its content.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;TodoList Component: &lt;/span&gt;The TodoList component will render a list of TodoItem components. It will receive an array of todos as a prop.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;&lt;br&gt;&lt;span style="font-weight: bold;"&gt;TodoForm Component: &lt;/span&gt;The TodoForm component will manage the input for adding new todos. It will use local state to keep track of the input value.&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Managing State and Props Between Components&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;We now have to manage the application’s whole state within the App component. This component will contain the todos array and the function for adding new todos.&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Best Practices for Component-Based Architecture in React&lt;/span&gt;&lt;/h2&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;To maintain your application easy to handle and grow, use these recommended practices:&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;&lt;strong&gt;Single Responsibility Principle: &lt;/strong&gt;Each component should be capable of performing a single task well. This facilitates understanding, testing, and maintenance. For example, the TodoItem component displays a single todo, whereas the TodoForm component handles input and submission.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;&lt;strong&gt;Reusability and Modularity: &lt;/strong&gt;Create components that can be used in multiple places throughout your app. This reduces duplicate code and makes maintenance easier. For example, you could design a Button component that can be utilized in different forms in all around the application.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;strong&gt;Proper State Management&lt;/strong&gt;&lt;/li&gt; 
 &lt;ul&gt; 
  &lt;li&gt;&lt;span&gt;Lifting State Up: Place the state to the nearest common parent of the components that require it. This allows components to communicate more effectively and avoids passing props down multiple tiers.&lt;/span&gt;&lt;/li&gt; 
  &lt;li&gt;&lt;span&gt;Context API: To handle the global state without having to use prop drilling, use the Context API. This is especially useful in larger projects with multiple nested components.&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt; 
 &lt;/ul&gt; 
 &lt;li&gt;&lt;span&gt;&lt;strong&gt;Using Hooks for Functional Components:&lt;/strong&gt; React hooks such as useState and useEffect enable functional components to manage state and lifecycle methods. As a result, managing complicated logic without the need for class components is made easier for functional components.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;h2&gt;&lt;span&gt;Refactoring the Todo List Application for Better Practices&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;To improve our Todo List application, we may develop a separate Button component for reuse:&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;&lt;br&gt;TodoForm‘s button can now be replaced with our Button component:&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Advanced Component Patterns&lt;/span&gt;&lt;/h2&gt; 
&lt;p style="font-weight: bold;"&gt;Higher-Order Components (HOCs)&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Functions known as HOCs accept a component and return a new one. This allows for the reuse of component logic, such as authentication checks or data fetching.&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;&lt;br&gt;Render Props&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Render Props is a mechanism for exchanging code between React components, utilizing a prop whose value is a function. This provides additional flexibility in component rendering.&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;&lt;br&gt;Compound Components&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;Compound components enable you to design a collection of components that interact to form a complicated UI element. This pattern allows you to encapsulate shared functionality while providing users with a simple API.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span style="white-space-collapse: preserve;"&gt; &lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;Example of Compound Components:&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;Testing React Components&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;Why Testing Matters in Component-Based Architecture&lt;/span&gt;&lt;span style="white-space-collapse: preserve;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;Testing helps to confirm that your components are functioning properly. It also makes it easier to change the code with assurance. A well-tested app has fewer bugs and problems, which speeds up development.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;Tools and Libraries for Testing&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;&lt;span&gt;Jest: A popular testing tool for React that offers many features for testing JavaScript apps.&lt;/span&gt;&lt;/li&gt; 
 &lt;li&gt;&lt;span&gt;React Testing Library: A library designed for testing React components, focusing on how users interact with them.&lt;/span&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;&lt;span style="font-weight: bold;"&gt;Writing Unit Tests for Components&lt;br&gt;&lt;/span&gt;&lt;span style="white-space-collapse: preserve;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;When you write unit tests, focus on how individual components behave instead of how they are built. This makes your tests stronger against changes in the component design.&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;Testing the Todo List Application Components&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Here’s an example of a unit test for the TodoForm component to ensure it correctly adds a new todo:&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
&lt;p style="font-weight: bold;"&gt;&lt;br&gt;Running Tests&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;To run the tests, you can use the following command:&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;&lt;br&gt;This command will execute all the tests in your application and provide feedback on their results.&lt;/span&gt;&lt;/p&gt; 
&lt;h2&gt;&lt;span&gt;Conclusion&lt;/span&gt;&lt;/h2&gt; 
&lt;p&gt;&lt;span&gt;Component-based architecture in React is a great way to build apps that are easy to scale and maintain. By following the ideas and best practices in this blog, you can make strong React apps that are simple to manage and grow.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;In this post, we looked at key ideas about React components, like props, state, and lifecycle methods. We built a basic Todo List app to show how to set up components and handle state well. We also talked about advanced methods like Higher-Order Components, Render Props, and Compound Components to improve your component design.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&lt;span&gt;Finally, we discussed the necessity of testing in component-based programming and demonstrated how to construct unit tests for your components. By implementing these techniques in your React projects, you’ll be prepared to tackle complex apps with confidence.&lt;/span&gt;&lt;/p&gt; 
&lt;p&gt;&amp;nbsp;&lt;/p&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fthinking-in-react-component-based-architecture&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <pubDate>Mon, 17 Mar 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/thinking-in-react-component-based-architecture</guid>
      <dc:date>2025-03-17T18:00:00Z</dc:date>
      <dc:creator>Ebrahim Ali</dc:creator>
    </item>
    <item>
      <title>Code Quality Matters: Understanding Smells and Heuristics in Code - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/code-quality-matters-understanding-smells-and-heuristics-in-code</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/code-quality-matters-understanding-smells-and-heuristics-in-code" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/61-Quality-Code-Matters.png" alt="Code Quality Matters: Understanding Smells and Heuristics in Code - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97082"&gt; 
  &lt;div class="elementor-element elementor-element-b3a5a3b e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-71122b93 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Introduction&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In the world of software development, the quality of your code plays a huge role in how &lt;span style="color: #000000;"&gt;successful&lt;/span&gt; your projects will be. Code quality isn’t just about making sure the code works—it’s about ensuring that it’s clean, readable, and easy to modify as your project grows. When code quality is poor, it can lead to many problems that slow down development, make bugs harder to fix, and cause a lot of frustration for everyone involved.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Why Code Quality Matters (Good code vs Bad code)&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Good code quality isn’t a luxury—it’s a necessity. When your code is clean and tidy, you spare yourself a great deal of unnecessary agony later. On the other hand, poor code quality can cripple your project in ways you may not even realize.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s why good code matters and what happens when you ignore it:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;1. Ease of Maintenance vs. Technical Debt&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; With great code, everything is organized in such a manner that somebody else would be able to modify the code with ease. In addition, new features may be added with zero repercussions.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When poor code is exhibited, it results in something called technical debt, where a quick fix creates a far bigger issue down the line. The more code is haphazardly organized, the more difficult it is to maintain.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Say you write a function that applies a discount, rather than having a centralized logic, you decide to duplicate and keep the discount logic in multiple files. Now, whenever any changes need to be made to the discount logic, you have to track down all copies and clones. And if you miss one, boom—bugs!&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;2. Fewer Bugs vs. Hard-to-Find Errors&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; There are fewer chances that the good code contains hidden bugs.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If a code looks unstructured and messy, it means finding errors in the code would be near impossible.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If another programmer, or even yourself from the future, comes back and sees a variable &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;x&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, it will not be immediately clear what that value is meant to portray, and therefore the programmer wastes a lot of time deciphering the meaning and purpose for &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;x&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. On the other hand, using good variable names like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;totalAmount&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; can eliminate such situations.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;3. Better Team Collaboration vs. Developer Frustration&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; A cohesive code style means manageably understand what has been written and one understands what parts of the code they can make contributions to.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Poorly arranged code adds more confusion to an already complex structure, wasting time while pouring huge amounts of irritation.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If two developers write similar functions with different naming styles—one calls it &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;fetchUserData()&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, another calls it &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;getUserInfo()&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;—it creates unnecessary confusion.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;4. Scalability vs. Rigid, Hard-to-Modify Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Well design code is capable of expanding without becoming an overly confusing assortment of parts.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Poor design choices early on make future expansion painful.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;There is no need to have one massive function that is responsible for everything. If you break tasks to smaller modular functions, your overall coding structure becomes easier to work with.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;5. Performance Optimization vs. Slow, Inefficient Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Code that is clean and devoid of unnecessary statements executes perfectly and optimally.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Careless code causes unnecessary constraints on the effectiveness with which a computer system functions.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;When an O(n) solution is available, an O(n²) loop will needlessly hinder the performance of your application. Realizing that writing efficient code from the beginning allows one to have a much easier experience down the road.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Understanding Code Smells: A Key Indicator of Code Quality&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;One of the ways to measure and assess the quality of your code is by looking for “code smells.” While a code smell doesn’t always mean the code is broken, it suggests that the code might need to be cleaned up or refactored to improve its quality.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;What is a Code Smell?&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;A code smell is any characteristic in your code that could indicate a deeper problem. These are usually easy to spot, even if you didn’t write the code yourself. Code smells act as a warning sign, letting you know that there might be areas in your code that need attention. They aren’t bugs—the code still works—but they point to places where the code could be improved.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Case Study: A Messy User Registration System&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Imagine a system where new users are registered, their details are validated, their email is verified, and they are assigned roles based on their account type. Below is the function handling this process:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-5ceb4c6 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This function &lt;/span&gt;&lt;strong&gt;works&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, but it is &lt;/span&gt;&lt;strong&gt;full of code smells&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. Let’s break down the problems using this example:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Long Methods:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When you find a method that is unnecessarily long, that’s usually a code smell. The above function is doing too many things:&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Validating passwords&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Checking email format&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Verifying the user’s age&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Storing user data&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Sending notifications&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This makes the function difficult to read and maintain.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;2. Too Many Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If you have a function that requires five or more parameters, it’s likely a code smell. The above function takes 10 parameters&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt; (name, email, password, confirmPassword, age, phone, address, accountType, notifyAdmin, sendWelcomeEmail)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. Passing this many parameters is confusing and makes the function hard to use.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;3. Duplicated Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Duplicating code in multiple places is a clear sign of a code smell. The function manually checks if &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;password !== confirmPassword and then separately checks if email.includes(“@”) &amp;amp;&amp;amp; email.includes(“.”)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. If these validations are needed elsewhere in the system, they will have to be duplicated.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;4. Feature Envy:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; This occurs when a method in one class spends too much time interacting with the data of another class. In practice, this could lead to tight coupling between classes, making it difficult to change or extend the code without affecting other parts of the system. For example the above function interacts too much with unrelated concerns:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It decides when to notify an admin.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It sends a welcome email.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It stores user information in the database.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It performs multiple types of validation.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;These tasks should belong to different parts of the system.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;5. Dead Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Dead code refers to code that is never executed but still exists in the codebase. For example:&amp;nbsp; If the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyAdmin and sendWelcomeEmail &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;flags are set to false, the related code does nothing. This conditional logic adds unnecessary complexity.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;6. Inconsistent Naming:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Consistency in naming is crucial for code readability. When similar things are named differently or different things are named similarly, it leads to confusion and makes the code harder to understand. For example, The function uses &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyAdmin&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, but &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;sendWelcomeEmail&lt;/strong&gt; &lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;instead of &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyUser&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. Naming inconsistencies like this make the code harder to understand.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;7. Obvious Behavior Is Unimplemented:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Functions should do what their names suggest. If a function’s name implies behavior that isn’t implemented, it creates a code smell. For example, the function &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;registerUser &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;implies it will create a new user, but it doesn’t explicitly return the user object. Instead, it just prints a message.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;8. Obsolete Comment:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; A comment that is outdated or no longer relevant is a code smell. Comments should provide value by explaining why something is done, not just what is done. When a comment becomes obsolete, it can mislead developers, making it harder to understand the current state of the code. For example: the function contains a comment&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;strong&gt;// It checks age limit up to 18 &lt;/strong&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. and if someone changes the logic without updating the comment, it will create confusion.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;9. Vertical Separation:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Variables and functions should be defined close to where they are used. A variable that is declared far from its usage or a private function defined far from its first invocation creates a smell, making the code harder to read and maintain.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;For example: the function jumps between unrelated concerns &lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;validation → database storage → notifications&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;, making it harder to follow.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;10.Too Much Information:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Exposing too many details, such as internal variables or methods, in a class interface leads to high coupling and low cohesion. This makes the class difficult to use and maintain. For instance, the function is directly handling how user data is stored, validated, and processed. A better approach would be to delegate these tasks to different modules.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;11. Magic Numbers:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Hardcoding literal numbers or strings in your code, instead of using named constants, is a common code smell. For example, the function hardcodes the age limit (18). It should instead use a named constant, like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;MINIMUM_AGE&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This list includes some of the most common code smells, but it’s not exhaustive. There are many other potential issues that could arise in your codebase.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9c090c2 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;The Impact of Code Smells&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;If you ignore code smells, you can run into several problems:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Increased Complexity:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As code smells accumulate, the codebase becomes more complex and difficult to work with. This complexity can lead to mistakes, as developers struggle to understand how different parts of the code interact.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Reduced Readability:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Code smells make your code harder to read, which in turn makes it harder to maintain. If the code is difficult to understand, new developers joining the project will have a hard time getting up to speed, leading to longer onboarding times and more errors.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Lower Flexibility:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Smelly code is harder to modify or extend. Adding new features or making changes becomes risky because the existing code is so tightly coupled or disorganized.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Higher Risk of Bugs:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Because smelly code is harder to understand, it’s easier to overlook potential issues, leading to bugs that can be difficult to track down and fix.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Code Quality: The Gap Between Academic Learning and Real-World Development&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;When we start to learn how to code either at a university or self taught, the first thing that we try to accomplish is learning how to solve problems in the best way possible. During these times, we tend to work alone or in small teams with little to no collaboration, and we try to get the code to do what we want in the shortest time possible. The problem with having this approach is that the code which is produced is often problematic as it may solve the problem but is not readable, maintainable, nor scalable. Because during one’s education, collaboration and following quality code standards are often lacking, this is the type of code students often produce. This tends to change during the transition to real world software development. Setting becomes heavily results-oriented in the sense that writing code which works is not enough, it involves writing code which is understandable, modifiable, and extendable to other developers. With the expectation that the code will eventually be worked on by several developers over time, new requirements arise which shift focus to cleanliness, organization, and scalability of the code. This is when developers understand the weight of code quality and the standards that are expected. The challenge in functioning on a professional level still persists amongst many developers even after they have mastered the ability to write code..&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Grasping the importance of code quality and learning how to identify and fix code smells is critical for any developer attempting to be successful in the real world of software engineering. It is not enough to simply write functioning code; one must consider its longevity and how easily it can be comprehended and maintained by others.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Heuristics: Tools for Identifying and Fixing Code Smells&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Heuristics are practical guidelines that can help you identify and address code smells. They provide a framework for evaluating your code and making decisions about when and how to refactor it.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Key Heuristics for Identifying Code Smells&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Keep Functions Small:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; This heuristic recommends that every function must do one thing. The functions must indeed be separated logically, if only to make it easier to understand, test and maintain the code. For example, you may have a function that validates data, processes, and produces output. It is easier to maintain if each task has its own function.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Prefer Composition Over Inheritance:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; In object-oriented programming, this heuristic suggests that it’s often better to compose objects using smaller, more focused classes rather than relying heavily on inheritance. This approach makes the code more flexible and easier to refactor.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Avoid Global Variables:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Since global variables are accessible from anywhere in the code, they can produce strange results and make debugging difficult. Local variables or encapsulated state within objects are much better options, since they reduce dependencies.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Refactor Often:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When you refactor your code regularly, it stays clean and does not accumulate too much technical debt. Everyone knows that code always has room for improvement, and as you make these improvements, you make sure that code smells do not develop.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Write Tests First:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Writing tests before you write your code ensures that your code is testable and encourages good design practices. Tests help catch potential problems early, reducing the risk of introducing new code smells.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Real-Life Example: Identifying and Fixing Code Smells&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;While we can’t cover every possible scenario, let’s explore a couple of common cases to see how code smells can be identified and addressed through refactoring, all within the context of real-world development.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;The Problematic Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s a piece of code written in javascript that has several code smells:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-1e28012 elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt; 
        &lt;pre class="highlight-height line-numbers language-javascript"&gt;&amp;nbsp;&lt;/pre&gt; 
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-43f0ed9 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;&lt;br&gt;Code Smells:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Long Method:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;processOrder&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; function is doing too many things—calculating shipping, applying discounts, processing payments, and updating the order status.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Too Many Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The function takes six parameters, making it hard to understand and use.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Feature Envy:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The function accesses multiple details about the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;order&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;customerType&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; objects, which could be encapsulated within their respective classes.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Flag Arguments:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The use of Boolean flags like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;isExpress&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; suggests that the function is doing multiple tasks, which should be split into separate functions.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Refactored Code:&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s how the javascript code could be refactored to address these smells:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-08f8a71 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;&lt;br&gt;Improvements Made:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Smaller Functions:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The original &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;processOrder&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; function has been broken down into smaller, more manageable and specific functions that accomplish one task each making it easier to add new functions without changing the existing ones.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Reduced Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Merging correlated data into objects, like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;customer &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;order&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, has also yielded a reduction in the number of parameters to be set.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Removed Flag Arguments:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The parameter &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;isExpress &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;of the main function has been omitted as it is a flag and is now being handled in the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;calculateShipping &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;function.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Encapsulation:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;applyDiscount &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;processPayment&lt;/strong&gt; &lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;functions now encapsulate details about the customer and payment methods, reducing the need for external code to manipulate these details.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The quality of code is important in building software that is maintainable, scalable, and dependable. Resolving and understanding the issue of code smells is a fundamental part to make sure that your codebase is both clean and functional. Being able to identify bad code and having rules of thumb for how to make improvements will make it easier for you to prevent a lot of future issues. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You shouldn’t let code smells turn into more serious problems. By addressing them early, you’ll create a codebase that is not only functional but also a pleasure to maintain and build upon. Better code means better software, happier developers, and successful projects.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97082"&gt; 
  &lt;div class="elementor-element elementor-element-b3a5a3b e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-71122b93 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Introduction&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In the world of software development, the quality of your code plays a huge role in how &lt;span style="color: #000000;"&gt;successful&lt;/span&gt; your projects will be. Code quality isn’t just about making sure the code works—it’s about ensuring that it’s clean, readable, and easy to modify as your project grows. When code quality is poor, it can lead to many problems that slow down development, make bugs harder to fix, and cause a lot of frustration for everyone involved.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Why Code Quality Matters (Good code vs Bad code)&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Good code quality isn’t a luxury—it’s a necessity. When your code is clean and tidy, you spare yourself a great deal of unnecessary agony later. On the other hand, poor code quality can cripple your project in ways you may not even realize.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s why good code matters and what happens when you ignore it:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;1. Ease of Maintenance vs. Technical Debt&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; With great code, everything is organized in such a manner that somebody else would be able to modify the code with ease. In addition, new features may be added with zero repercussions.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When poor code is exhibited, it results in something called technical debt, where a quick fix creates a far bigger issue down the line. The more code is haphazardly organized, the more difficult it is to maintain.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Say you write a function that applies a discount, rather than having a centralized logic, you decide to duplicate and keep the discount logic in multiple files. Now, whenever any changes need to be made to the discount logic, you have to track down all copies and clones. And if you miss one, boom—bugs!&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;2. Fewer Bugs vs. Hard-to-Find Errors&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; There are fewer chances that the good code contains hidden bugs.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If a code looks unstructured and messy, it means finding errors in the code would be near impossible.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If another programmer, or even yourself from the future, comes back and sees a variable &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;x&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, it will not be immediately clear what that value is meant to portray, and therefore the programmer wastes a lot of time deciphering the meaning and purpose for &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;x&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. On the other hand, using good variable names like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;totalAmount&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; can eliminate such situations.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;3. Better Team Collaboration vs. Developer Frustration&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; A cohesive code style means manageably understand what has been written and one understands what parts of the code they can make contributions to.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Poorly arranged code adds more confusion to an already complex structure, wasting time while pouring huge amounts of irritation.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If two developers write similar functions with different naming styles—one calls it &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;fetchUserData()&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, another calls it &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;getUserInfo()&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;—it creates unnecessary confusion.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;4. Scalability vs. Rigid, Hard-to-Modify Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Well design code is capable of expanding without becoming an overly confusing assortment of parts.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Poor design choices early on make future expansion painful.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;There is no need to have one massive function that is responsible for everything. If you break tasks to smaller modular functions, your overall coding structure becomes easier to work with.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;5. Performance Optimization vs. Slow, Inefficient Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Good Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Code that is clean and devoid of unnecessary statements executes perfectly and optimally.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Bad Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Careless code causes unnecessary constraints on the effectiveness with which a computer system functions.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;strong&gt;&lt;br&gt;&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;When an O(n) solution is available, an O(n²) loop will needlessly hinder the performance of your application. Realizing that writing efficient code from the beginning allows one to have a much easier experience down the road.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Understanding Code Smells: A Key Indicator of Code Quality&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;One of the ways to measure and assess the quality of your code is by looking for “code smells.” While a code smell doesn’t always mean the code is broken, it suggests that the code might need to be cleaned up or refactored to improve its quality.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;What is a Code Smell?&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;A code smell is any characteristic in your code that could indicate a deeper problem. These are usually easy to spot, even if you didn’t write the code yourself. Code smells act as a warning sign, letting you know that there might be areas in your code that need attention. They aren’t bugs—the code still works—but they point to places where the code could be improved.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Case Study: A Messy User Registration System&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Imagine a system where new users are registered, their details are validated, their email is verified, and they are assigned roles based on their account type. Below is the function handling this process:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-5ceb4c6 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This function &lt;/span&gt;&lt;strong&gt;works&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, but it is &lt;/span&gt;&lt;strong&gt;full of code smells&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. Let’s break down the problems using this example:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Long Methods:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When you find a method that is unnecessarily long, that’s usually a code smell. The above function is doing too many things:&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Validating passwords&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Checking email format&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Verifying the user’s age&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Storing user data&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Sending notifications&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This makes the function difficult to read and maintain.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;2. Too Many Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; If you have a function that requires five or more parameters, it’s likely a code smell. The above function takes 10 parameters&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt; (name, email, password, confirmPassword, age, phone, address, accountType, notifyAdmin, sendWelcomeEmail)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. Passing this many parameters is confusing and makes the function hard to use.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;3. Duplicated Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Duplicating code in multiple places is a clear sign of a code smell. The function manually checks if &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;password !== confirmPassword and then separately checks if email.includes(“@”) &amp;amp;&amp;amp; email.includes(“.”)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. If these validations are needed elsewhere in the system, they will have to be duplicated.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;4. Feature Envy:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; This occurs when a method in one class spends too much time interacting with the data of another class. In practice, this could lead to tight coupling between classes, making it difficult to change or extend the code without affecting other parts of the system. For example the above function interacts too much with unrelated concerns:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It decides when to notify an admin.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It sends a welcome email.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It stores user information in the database.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;It performs multiple types of validation.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;These tasks should belong to different parts of the system.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;5. Dead Code:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Dead code refers to code that is never executed but still exists in the codebase. For example:&amp;nbsp; If the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyAdmin and sendWelcomeEmail &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;flags are set to false, the related code does nothing. This conditional logic adds unnecessary complexity.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;6. Inconsistent Naming:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Consistency in naming is crucial for code readability. When similar things are named differently or different things are named similarly, it leads to confusion and makes the code harder to understand. For example, The function uses &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyAdmin&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, but &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;sendWelcomeEmail&lt;/strong&gt; &lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;instead of &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;notifyUser&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. Naming inconsistencies like this make the code harder to understand.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;7. Obvious Behavior Is Unimplemented:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Functions should do what their names suggest. If a function’s name implies behavior that isn’t implemented, it creates a code smell. For example, the function &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;registerUser &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;implies it will create a new user, but it doesn’t explicitly return the user object. Instead, it just prints a message.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;8. Obsolete Comment:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; A comment that is outdated or no longer relevant is a code smell. Comments should provide value by explaining why something is done, not just what is done. When a comment becomes obsolete, it can mislead developers, making it harder to understand the current state of the code. For example: the function contains a comment&lt;/span&gt; &lt;span style="color: #008000;"&gt;&lt;strong&gt;// It checks age limit up to 18 &lt;/strong&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;. and if someone changes the logic without updating the comment, it will create confusion.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;9. Vertical Separation:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Variables and functions should be defined close to where they are used. A variable that is declared far from its usage or a private function defined far from its first invocation creates a smell, making the code harder to read and maintain.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;For example: the function jumps between unrelated concerns &lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;validation → database storage → notifications&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;)&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;, making it harder to follow.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;10.Too Much Information:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Exposing too many details, such as internal variables or methods, in a class interface leads to high coupling and low cohesion. This makes the class difficult to use and maintain. For instance, the function is directly handling how user data is stored, validated, and processed. A better approach would be to delegate these tasks to different modules.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;11. Magic Numbers:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Hardcoding literal numbers or strings in your code, instead of using named constants, is a common code smell. For example, the function hardcodes the age limit (18). It should instead use a named constant, like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;MINIMUM_AGE&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This list includes some of the most common code smells, but it’s not exhaustive. There are many other potential issues that could arise in your codebase.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9c090c2 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;The Impact of Code Smells&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;If you ignore code smells, you can run into several problems:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Increased Complexity:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; As code smells accumulate, the codebase becomes more complex and difficult to work with. This complexity can lead to mistakes, as developers struggle to understand how different parts of the code interact.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Reduced Readability:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Code smells make your code harder to read, which in turn makes it harder to maintain. If the code is difficult to understand, new developers joining the project will have a hard time getting up to speed, leading to longer onboarding times and more errors.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Lower Flexibility:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Smelly code is harder to modify or extend. Adding new features or making changes becomes risky because the existing code is so tightly coupled or disorganized.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Higher Risk of Bugs:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Because smelly code is harder to understand, it’s easier to overlook potential issues, leading to bugs that can be difficult to track down and fix.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Code Quality: The Gap Between Academic Learning and Real-World Development&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;When we start to learn how to code either at a university or self taught, the first thing that we try to accomplish is learning how to solve problems in the best way possible. During these times, we tend to work alone or in small teams with little to no collaboration, and we try to get the code to do what we want in the shortest time possible. The problem with having this approach is that the code which is produced is often problematic as it may solve the problem but is not readable, maintainable, nor scalable. Because during one’s education, collaboration and following quality code standards are often lacking, this is the type of code students often produce. This tends to change during the transition to real world software development. Setting becomes heavily results-oriented in the sense that writing code which works is not enough, it involves writing code which is understandable, modifiable, and extendable to other developers. With the expectation that the code will eventually be worked on by several developers over time, new requirements arise which shift focus to cleanliness, organization, and scalability of the code. This is when developers understand the weight of code quality and the standards that are expected. The challenge in functioning on a professional level still persists amongst many developers even after they have mastered the ability to write code..&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Grasping the importance of code quality and learning how to identify and fix code smells is critical for any developer attempting to be successful in the real world of software engineering. It is not enough to simply write functioning code; one must consider its longevity and how easily it can be comprehended and maintained by others.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Heuristics: Tools for Identifying and Fixing Code Smells&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Heuristics are practical guidelines that can help you identify and address code smells. They provide a framework for evaluating your code and making decisions about when and how to refactor it.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Key Heuristics for Identifying Code Smells&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Keep Functions Small:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; This heuristic recommends that every function must do one thing. The functions must indeed be separated logically, if only to make it easier to understand, test and maintain the code. For example, you may have a function that validates data, processes, and produces output. It is easier to maintain if each task has its own function.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Prefer Composition Over Inheritance:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; In object-oriented programming, this heuristic suggests that it’s often better to compose objects using smaller, more focused classes rather than relying heavily on inheritance. This approach makes the code more flexible and easier to refactor.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Avoid Global Variables:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Since global variables are accessible from anywhere in the code, they can produce strange results and make debugging difficult. Local variables or encapsulated state within objects are much better options, since they reduce dependencies.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Refactor Often:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; When you refactor your code regularly, it stays clean and does not accumulate too much technical debt. Everyone knows that code always has room for improvement, and as you make these improvements, you make sure that code smells do not develop.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Write Tests First:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Writing tests before you write your code ensures that your code is testable and encourages good design practices. Tests help catch potential problems early, reducing the risk of introducing new code smells.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Real-Life Example: Identifying and Fixing Code Smells&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;While we can’t cover every possible scenario, let’s explore a couple of common cases to see how code smells can be identified and addressed through refactoring, all within the context of real-world development.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;The Problematic Code&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s a piece of code written in javascript that has several code smells:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-1e28012 elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt; 
        &lt;pre class="highlight-height line-numbers language-javascript"&gt;&amp;nbsp;&lt;/pre&gt; 
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-43f0ed9 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;&lt;br&gt;Code Smells:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Long Method:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;processOrder&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; function is doing too many things—calculating shipping, applying discounts, processing payments, and updating the order status.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Too Many Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The function takes six parameters, making it hard to understand and use.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Feature Envy:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The function accesses multiple details about the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;order&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;customerType&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; objects, which could be encapsulated within their respective classes.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Flag Arguments:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The use of Boolean flags like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;isExpress&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; suggests that the function is doing multiple tasks, which should be split into separate functions.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;p&gt;&lt;strong&gt;Refactored Code:&lt;/strong&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s how the javascript code could be refactored to address these smells:&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-08f8a71 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;&lt;br&gt;Improvements Made:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Smaller Functions:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The original &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;processOrder&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; function has been broken down into smaller, more manageable and specific functions that accomplish one task each making it easier to add new functions without changing the existing ones.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Reduced Parameters:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; Merging correlated data into objects, like &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;customer &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;order&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;, has also yielded a reduction in the number of parameters to be set.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Removed Flag Arguments:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The parameter &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;isExpress &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;of the main function has been omitted as it is a flag and is now being handled in the &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;calculateShipping &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;function.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Encapsulation:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; The &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;strong&gt;applyDiscount &lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;and &lt;/span&gt;&lt;span style="color: #008000;"&gt;&lt;em&gt;&lt;span style="font-weight: 400;"&gt;&lt;strong&gt;processPayment&lt;/strong&gt; &lt;/span&gt;&lt;/em&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;functions now encapsulate details about the customer and payment methods, reducing the need for external code to manipulate these details.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;The quality of code is important in building software that is maintainable, scalable, and dependable. Resolving and understanding the issue of code smells is a fundamental part to make sure that your codebase is both clean and functional. Being able to identify bad code and having rules of thumb for how to make improvements will make it easier for you to prevent a lot of future issues. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You shouldn’t let code smells turn into more serious problems. By addressing them early, you’ll create a codebase that is not only functional but also a pleasure to maintain and build upon. Better code means better software, happier developers, and successful projects.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fcode-quality-matters-understanding-smells-and-heuristics-in-code&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <pubDate>Wed, 12 Mar 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/code-quality-matters-understanding-smells-and-heuristics-in-code</guid>
      <dc:date>2025-03-12T18:00:00Z</dc:date>
      <dc:creator>Omor Faruk Rakib</dc:creator>
    </item>
    <item>
      <title>Elegance in Databases: The Art of SQL vs NoSQL - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/elegance-in-databases-the-art-of-sql-vs-nosql</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/elegance-in-databases-the-art-of-sql-vs-nosql" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Elegence%20in%20Database.webp" alt="Elegance in Databases: The Art of SQL vs NoSQL" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97004"&gt; 
  &lt;div class="elementor-element elementor-element-4cfee2c3 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-73c4d60f elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Database, the center point of each application, plays a crucial role as data is always needed to execute a project and must be stored in some fashion. As applications grow in complexity and scale, the process of storing and managing data becomes more difficult.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;When it comes to storing and managing data, developers face the challenging decision of choosing between traditional SQL databases or modern NoSQL databases. This comparison—&lt;strong&gt;SQL vs NoSQL&lt;/strong&gt;—highlights their unique strengths, weaknesses, and ideal use cases, making the decision even more daunting.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;In this blog, we will dive into the art of &lt;strong&gt;SQL vs NoSQL&lt;/strong&gt;, comparing their features, examining their suitability for different scenarios, and understanding the principles that help us choose between the two. For this exploration, we benchmark one popular SQL database, PostgreSQL, and a leading NoSQL database, &lt;strong&gt;DynamoDB.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;What is Postgresql?&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;PostgreSQL&amp;nbsp; is an open source rdbms(relational database management system) which evolved from the ingres project in the university of california. It follows the traditional ACID (Atomicity, Consistency, Isolation, Durability) properties, making it highly reliable and suitable for various applications.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;What is DynamoDB?&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB is on the other hand one of fastest growing modern NoSQL databases which is fully managed by AWS(Amazon Web Services) and follows the single table design pattern. It is designed to handle high volumes of unstructured and schemaless data and traffic. It automatically scales up or down according to the workload.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Design Patterns&lt;/h2&gt; 
      &lt;p&gt;&lt;strong&gt;Postgresql&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;ACID Properties:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; It follows the basic acid properties which a must have for sql databases. Atomicity ensures either a transaction will commit or not and there is no in between. Consistency ensures data should remain consistent no matter from where the query comes from. Isolation ensures only one person can write into the database in a single point of time and finally, durability ensures committed data will persist throughout the time.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Schema Based Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It uses a structured schema with different tables. Each table has a primary key(unique identifier) and is connected to another table through a foreign key. It has also join operations to combine two tables to fetch data as well as indexing to fetch data quickly.&amp;nbsp;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Here is a sample table design in postgresql where &lt;/span&gt;&lt;strong&gt;CustomerID &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is defined as primary key in the &lt;/span&gt;&lt;strong&gt;Customers &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table and as far as the &lt;/span&gt;&lt;strong&gt;Orders &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table is concern &lt;/span&gt;&lt;strong&gt;OrderId &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is the primary key and &lt;/span&gt;&lt;strong&gt;CustomerID &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is the foreign key which is outlined in red as how the both table are being connected&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c2a242f elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-6cc846b elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;3.&lt;strong&gt; &lt;span style="font-size: 16px;"&gt;Indexing:&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt; In SQL also in Postgresql uses different types of indexing to retrieve the data faster as the data grows and traditional sql databases tend to slow it down as the query uses sequential searches. So indexing comes as a savior as it uses B-tree to speed up the search.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;4. &lt;strong&gt;Normalization: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Organize data into related tables to reduce data redundancy. There are various types of normalization like 1NF, 2NF,3NF. This process involves large tables divided into smaller ones and multiple ones ensuring each table focuses on one topic. For example let us consider a table &lt;/span&gt;&lt;strong&gt;order &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table has the following items&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td colspan="4"&gt;&lt;strong&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="font-size: 14px;"&gt;Order table&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Customer_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_date&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Product_id&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;101&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1,2&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;102&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3,4&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;As we can see the &lt;/span&gt;&lt;strong&gt;product_id &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;column holds multiple entries which violates the idea of normalization. As normalization states that each column should hold data atomic we need to break down the table into two and introduce &lt;/span&gt;&lt;strong&gt;order_items &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table and new table should look like as follows&lt;/span&gt;&lt;/p&gt; 
      &lt;table style="width: 35.9664%;"&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 99.9544%;" colspan="3"&gt;&lt;strong&gt;&lt;span style="font-size: 14px;"&gt;Order table&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Customer_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_date&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;101&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;102&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td colspan="4"&gt; &lt;p style="font-weight: bold;"&gt;&lt;span style="font-size: 14px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Order items table&lt;/span&gt;&lt;/p&gt; &lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Item_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Product_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Quantity&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;5&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;span style="font-size: 16px;"&gt;Here we saw the basic operation on normalization which breaks the initial two tables into two and this is called &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;1NF. &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;However the tables can be further normalized and in order to retrieve data we might need join operation&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;5.&lt;strong&gt; Aggregation: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;SQL aggregation functions are used to perform calculations on multiple rows of a table’s column and return a single value. Common aggregate functions include &lt;/span&gt;&lt;strong&gt;SUM&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which adds up all values in a column; &lt;/span&gt;&lt;strong&gt;AVG&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which calculates the average; &lt;/span&gt;&lt;strong&gt;COUNT&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which counts the number of rows; &lt;/span&gt;&lt;strong&gt;MAX&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which finds the highest value; and MIN, which finds the lowest value. These functions are often used with the GROUP BY clause to group rows sharing a common attribute and apply the aggregate function to each group. For example,&lt;/span&gt;&lt;strong&gt; SELECT department, COUNT(*) FROM employees GROUP BY department &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;counts employees in each department.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;6. &lt;strong&gt;OLAP: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;OLAP (Online Analytical Processing) in SQL is a powerful data analysis approach used for complex querying and reporting. It enables users to perform multidimensional analysis of large datasets stored in data warehouses. OLAP operations include slicing, dicing, drilling down, and pivoting to view data from different perspectives. SQL-based OLAP leverages aggregate functions, groupings, and hierarchical data structures to provide insights into business metrics. For example, a retail company can analyze sales data by product, region, and time. OLAP enhances decision-making by allowing interactive analysis and quick retrieval of aggregated data, making it essential for business intelligence and strategic planning.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;DynamoDB&lt;/h2&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Single Table Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Unlike the traditional SQL design DynamoDB follows single table design meaning it stores all types of data in a single table rather than multiple ones. This type of design introduces two new key words one is partition key and another one is sort key. In single table design we can declare each row as an item and if the items are being corresponding to one partition are called item collection. There some keyword which are being used in the single table design as follows&amp;nbsp;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Partition Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;In dynamodb partition key defines how data is being distributed among the partitions.It is also referred as hash key as data data in dynamodb is stored and retrieved as hash. Whenever a data is being inserted it generates a hash and based on the hash it stores the data into the corresponding partition and same goes for retrieving data from a particular partition.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Sort Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Sort key is determined as to how a data is being organized in a particular partition. There is always a possibility that items have the same value for the partition key but there must be a different value for the sort key.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Primary Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Primary key uniquely identifies a row. Sometimes the partition key is regarded as the primary key, however it can be the combination of both partition key and sort key.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d752c08 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9f12c08 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;br&gt;2. &lt;strong&gt;Event Driven Architecture: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;dynamoDB streams is a feature of dynamoDB which captures any&amp;nbsp; crud operations in a dynamoDB table and records them into streams. It allows any application to track any types of changes and triggering an event. Each event in the stream is called a stream record which contains information about the item affected and the type of modification. For e When a new order is placed in an &lt;/span&gt;&lt;strong&gt;order &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;stable, a stream record is generated. A Lambda function can be triggered to process the order, update inventory, send notifications, or replicate the order to another data store.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-44aa039 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-2ee5e6e elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;3. &lt;strong&gt;Time to Leave(TTL): &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Time to leave is a feature of dynamoDB which is responsible for automatically deleting items from a table after a particular time. We don’t need to delete data manually or by query like in SQL. This reduces the storage cost by removing unnecessary data which is no longer needed after a particular amount of time which is about 48 hours by default.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;4. &lt;strong&gt;Access Pattern: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;One of the most important yet most challenging tasks is to define the access pattern for your dynamoDB. The design solely depends on what kind of query can happen after the application is being live. The design of partition key and sort key depends on the access pattern. Depending on the query the database will first go to the desired partition where the desired data might reside. So we need to define the access pattern first before designing the database&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;5.&lt;strong&gt; Global and Local Secondary Indexes: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It enables another layer of flexibility as far as querying is concerned. In LSI one can add another sort key along with the present sort key and partition key. But if one uses an LSI the partition size automatically becomes a 10gb of size. One can use at most 5 LSI for one table design and it comes free of cost meaning aws will not charge you any penny if one uses any kinds of LSI in a table.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c16b638 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c9a3ddf elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;On the other hand GSI allows you to add another partition key and sort key in a table. What it does is it copies all the data from the table and in that table we can apply the partition key and sort key. AWS allows you to used up to 20 GSI for a particular table but in that case dynamoDB will charge for each write and read operations.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-fe80fec elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;br&gt; 
      &lt;br&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-8ee2faf elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container" style="font-size: 18px;"&gt; 
      &lt;p style="font-size: 16px;"&gt;6. &lt;strong&gt;Data Duplication: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;One of the main features of DynamoDB is the ability to duplicate data, which significantly enhances query performance and response times. However, data duplication increases storage costs, but AWS never charges for storage and only charges for write and read operations. However, while data duplication improves efficiency significantly, it also has drawbacks. Every change must be propagated across all duplicates, increasing the number of write operations that AWS charges for.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;When to Choose PostgreSQL or DynamoDB?&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Choose Postgresql&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;strong&gt;Complex Queries and Joins are Necessary: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Though join operations are sometimes costlier. PostgreSQL excels with complicated queries and joins, allowing you to quickly access and manage relevant data from numerous tables. Here is an example operations of join query&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;strong&gt;SELECT customers.name, SUM(orders.amount) FROM customers JOIN orders ON customers.id = orders.customer_id GROUP BY customers.name;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;br&gt;2.&lt;strong&gt; Extensive Analytical and Reporting Needs: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If your application needs heavy analytical reports postgresql should be the go to databases as it can handle extensive queries and also reporting data&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;3. &lt;strong&gt;Data Integrity and Consistency : &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Foreign keys, unique constraints, and check constraints are among PostgreSQL’s several data integrity capabilities, helping in the maintenance of consistent and correct data.&lt;/span&gt;&lt;/p&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;CREATE TABLE products&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;( product_id SERIAL PRIMARY KEY,&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;name VARCHAR(100) NOT NULL,&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;price NUMERIC CHECK (price &amp;gt; 0),&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;stock INT CHECK (stock &amp;gt;= 0) );&lt;/strong&gt;&lt;/p&gt; &lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;span style="font-size: 16px;"&gt;Using constraints to enforce data integrity.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 18px;"&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Choose DynamoDB&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Scalability and Performance are Top Priorities: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB’s seamless scalability and flexibility to manage heavy traffic make it ideal for applications with varying or enormous workloads.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Faster Response: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If one’s access patterns are defined and you designed your database efficiently DynamoDB will always retrieve data faster than SQL regardless of the data volume it will always fetch data faster.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Flexible Data Models and Schema-less Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB’s schema-less design enables flexible data modeling, accepting various data structures without specified schema.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;High Availability and Fault Tolerance: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;&amp;nbsp;DynamoDB’s multi-region, multi-active architecture provides high availability and fault tolerance, ensuring that your application remains available even in the face of regional outages.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Scenario&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Restaurant Management System&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Consider a restaurant management system: customers go through the menus and and according to the menu they place orders and waiters serve the orders.In that case the following requirements are necessary&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Complex queries and joins for reporting.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;High data integrity and consistency.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Scalability for handling variable traffic.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Low-latency read and write operations.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;strong&gt;Probable Access Pattern:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Get all the menu&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Add an order&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Daily/monthly/yearly total order quantity/amount&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Postgresql: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It can be used for complex queries and joins operations for reporting purposes. Also any type of OLAP operations like how many orders for a particular time or over a period of time or how much sales generates over a period of time.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;DynamoDB&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: It can be used for faster read and write operations, for example retrieving all the menu items from the menu or adding an order. As these operations need faster response and also it can be used for variable traffic like when more users are entering the menu item or add in an order it should automatically scale up or down depending on the situations.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;PostgreSQL and DynamoDB are both powerful database systems, with unique advantages based on your application’s requirements. PostgreSQL excels in handling complicated queries, transactions, and relational data models, making it ideal for traditional corporate applications and data warehousing. DynamoDB, on the other hand, provides seamless scalability, faster query response, low latency performance, and flexible data modeling, making it perfect for contemporary, high-traffic applications, IoT systems, and real-time analytics.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;By evaluating your application’s specific needs around data structure, scalability, performance, and integration requirements with other AWS services, you can make an informed decision between PostgreSQL and DynamoDB. Both databases offer robust solutions to effectively manage and scale your data infrastructure, ensuring optimal performance and reliability for your application.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-97004"&gt; 
  &lt;div class="elementor-element elementor-element-4cfee2c3 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-73c4d60f elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;Database, the center point of each application, plays a crucial role as data is always needed to execute a project and must be stored in some fashion. As applications grow in complexity and scale, the process of storing and managing data becomes more difficult.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;When it comes to storing and managing data, developers face the challenging decision of choosing between traditional SQL databases or modern NoSQL databases. This comparison—&lt;strong&gt;SQL vs NoSQL&lt;/strong&gt;—highlights their unique strengths, weaknesses, and ideal use cases, making the decision even more daunting.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;In this blog, we will dive into the art of &lt;strong&gt;SQL vs NoSQL&lt;/strong&gt;, comparing their features, examining their suitability for different scenarios, and understanding the principles that help us choose between the two. For this exploration, we benchmark one popular SQL database, PostgreSQL, and a leading NoSQL database, &lt;strong&gt;DynamoDB.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;What is Postgresql?&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;PostgreSQL&amp;nbsp; is an open source rdbms(relational database management system) which evolved from the ingres project in the university of california. It follows the traditional ACID (Atomicity, Consistency, Isolation, Durability) properties, making it highly reliable and suitable for various applications.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;What is DynamoDB?&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB is on the other hand one of fastest growing modern NoSQL databases which is fully managed by AWS(Amazon Web Services) and follows the single table design pattern. It is designed to handle high volumes of unstructured and schemaless data and traffic. It automatically scales up or down according to the workload.&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Design Patterns&lt;/h2&gt; 
      &lt;p&gt;&lt;strong&gt;Postgresql&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;ACID Properties:&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; It follows the basic acid properties which a must have for sql databases. Atomicity ensures either a transaction will commit or not and there is no in between. Consistency ensures data should remain consistent no matter from where the query comes from. Isolation ensures only one person can write into the database in a single point of time and finally, durability ensures committed data will persist throughout the time.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Schema Based Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It uses a structured schema with different tables. Each table has a primary key(unique identifier) and is connected to another table through a foreign key. It has also join operations to combine two tables to fetch data as well as indexing to fetch data quickly.&amp;nbsp;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Here is a sample table design in postgresql where &lt;/span&gt;&lt;strong&gt;CustomerID &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is defined as primary key in the &lt;/span&gt;&lt;strong&gt;Customers &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table and as far as the &lt;/span&gt;&lt;strong&gt;Orders &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table is concern &lt;/span&gt;&lt;strong&gt;OrderId &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is the primary key and &lt;/span&gt;&lt;strong&gt;CustomerID &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;is the foreign key which is outlined in red as how the both table are being connected&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c2a242f elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="730" height="311" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image1-1.png?width=730&amp;amp;height=311&amp;amp;name=image1-1.png" class="attachment-large size-large wp-image-97714" alt="Elegance in Databases: The Art of SQL vs NoSQL"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-6cc846b elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;3.&lt;strong&gt; &lt;span style="font-size: 16px;"&gt;Indexing:&lt;/span&gt;&lt;/strong&gt;&lt;span style="font-weight: 400; font-size: 16px;"&gt; In SQL also in Postgresql uses different types of indexing to retrieve the data faster as the data grows and traditional sql databases tend to slow it down as the query uses sequential searches. So indexing comes as a savior as it uses B-tree to speed up the search.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;4. &lt;strong&gt;Normalization: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Organize data into related tables to reduce data redundancy. There are various types of normalization like 1NF, 2NF,3NF. This process involves large tables divided into smaller ones and multiple ones ensuring each table focuses on one topic. For example let us consider a table &lt;/span&gt;&lt;strong&gt;order &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table has the following items&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td colspan="4"&gt;&lt;strong&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="font-size: 14px;"&gt;Order table&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Customer_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_date&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Product_id&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;101&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1,2&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;102&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3,4&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;As we can see the &lt;/span&gt;&lt;strong&gt;product_id &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;column holds multiple entries which violates the idea of normalization. As normalization states that each column should hold data atomic we need to break down the table into two and introduce &lt;/span&gt;&lt;strong&gt;order_items &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;table and new table should look like as follows&lt;/span&gt;&lt;/p&gt; 
      &lt;table style="width: 35.9664%;"&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 99.9544%;" colspan="3"&gt;&lt;strong&gt;&lt;span style="font-size: 14px;"&gt;Order table&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Customer_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_date&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;101&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td style="width: 34.225%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 31.4727%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;102&lt;/span&gt;&lt;/td&gt; 
         &lt;td style="width: 34.2567%;"&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;12-11-2003&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td colspan="4"&gt; &lt;p style="font-weight: bold;"&gt;&lt;span style="font-size: 14px;"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Order items table&lt;/span&gt;&lt;/p&gt; &lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Item_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Order_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Product_id&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;Quantity&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;1&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;3&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;2&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;4&lt;/span&gt;&lt;/td&gt; 
         &lt;td&gt;&lt;span style="font-weight: 400; font-size: 14px;"&gt;5&lt;/span&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;span style="font-size: 16px;"&gt;Here we saw the basic operation on normalization which breaks the initial two tables into two and this is called &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;1NF. &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;However the tables can be further normalized and in order to retrieve data we might need join operation&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;5.&lt;strong&gt; Aggregation: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;SQL aggregation functions are used to perform calculations on multiple rows of a table’s column and return a single value. Common aggregate functions include &lt;/span&gt;&lt;strong&gt;SUM&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which adds up all values in a column; &lt;/span&gt;&lt;strong&gt;AVG&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which calculates the average; &lt;/span&gt;&lt;strong&gt;COUNT&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which counts the number of rows; &lt;/span&gt;&lt;strong&gt;MAX&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which finds the highest value; and MIN, which finds the lowest value. These functions are often used with the GROUP BY clause to group rows sharing a common attribute and apply the aggregate function to each group. For example,&lt;/span&gt;&lt;strong&gt; SELECT department, COUNT(*) FROM employees GROUP BY department &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;counts employees in each department.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-size: 16px;"&gt;6. &lt;strong&gt;OLAP: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;OLAP (Online Analytical Processing) in SQL is a powerful data analysis approach used for complex querying and reporting. It enables users to perform multidimensional analysis of large datasets stored in data warehouses. OLAP operations include slicing, dicing, drilling down, and pivoting to view data from different perspectives. SQL-based OLAP leverages aggregate functions, groupings, and hierarchical data structures to provide insights into business metrics. For example, a retail company can analyze sales data by product, region, and time. OLAP enhances decision-making by allowing interactive analysis and quick retrieval of aggregated data, making it essential for business intelligence and strategic planning.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;DynamoDB&lt;/h2&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Single Table Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Unlike the traditional SQL design DynamoDB follows single table design meaning it stores all types of data in a single table rather than multiple ones. This type of design introduces two new key words one is partition key and another one is sort key. In single table design we can declare each row as an item and if the items are being corresponding to one partition are called item collection. There some keyword which are being used in the single table design as follows&amp;nbsp;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;ul style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Partition Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;In dynamodb partition key defines how data is being distributed among the partitions.It is also referred as hash key as data data in dynamodb is stored and retrieved as hash. Whenever a data is being inserted it generates a hash and based on the hash it stores the data into the corresponding partition and same goes for retrieving data from a particular partition.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;ul style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Sort Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Sort key is determined as to how a data is being organized in a particular partition. There is always a possibility that items have the same value for the partition key but there must be a different value for the sort key.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Primary Key: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Primary key uniquely identifies a row. Sometimes the partition key is regarded as the primary key, however it can be the combination of both partition key and sort key.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d752c08 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="402" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image2-1024x402.png?width=1024&amp;amp;height=402&amp;amp;name=image2-1024x402.png" class="attachment-large size-large wp-image-97715" alt="Elegance in Databases: The Art of SQL vs NoSQL"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9f12c08 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;br&gt;2. &lt;strong&gt;Event Driven Architecture: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;dynamoDB streams is a feature of dynamoDB which captures any&amp;nbsp; crud operations in a dynamoDB table and records them into streams. It allows any application to track any types of changes and triggering an event. Each event in the stream is called a stream record which contains information about the item affected and the type of modification. For e When a new order is placed in an &lt;/span&gt;&lt;strong&gt;order &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;stable, a stream record is generated. A Lambda function can be triggered to process the order, update inventory, send notifications, or replicate the order to another data store.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-44aa039 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="607" height="294" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image5-2.png?width=607&amp;amp;height=294&amp;amp;name=image5-2.png" class="attachment-large size-large wp-image-97716" alt="DynamoDB"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-2ee5e6e elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;3. &lt;strong&gt;Time to Leave(TTL): &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Time to leave is a feature of dynamoDB which is responsible for automatically deleting items from a table after a particular time. We don’t need to delete data manually or by query like in SQL. This reduces the storage cost by removing unnecessary data which is no longer needed after a particular amount of time which is about 48 hours by default.&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;4. &lt;strong&gt;Access Pattern: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;One of the most important yet most challenging tasks is to define the access pattern for your dynamoDB. The design solely depends on what kind of query can happen after the application is being live. The design of partition key and sort key depends on the access pattern. Depending on the query the database will first go to the desired partition where the desired data might reside. So we need to define the access pattern first before designing the database&amp;nbsp;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;5.&lt;strong&gt; Global and Local Secondary Indexes: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It enables another layer of flexibility as far as querying is concerned. In LSI one can add another sort key along with the present sort key and partition key. But if one uses an LSI the partition size automatically becomes a 10gb of size. One can use at most 5 LSI for one table design and it comes free of cost meaning aws will not charge you any penny if one uses any kinds of LSI in a table.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c16b638 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="925" height="554" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image4-1-1.png?width=925&amp;amp;height=554&amp;amp;name=image4-1-1.png" class="attachment-large size-large wp-image-97039" alt=""&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c9a3ddf elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;On the other hand GSI allows you to add another partition key and sort key in a table. What it does is it copies all the data from the table and in that table we can apply the partition key and sort key. AWS allows you to used up to 20 GSI for a particular table but in that case dynamoDB will charge for each write and read operations.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-fe80fec elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1014" height="201" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image3.png?width=1014&amp;amp;height=201&amp;amp;name=image3.png" class="attachment-large size-large wp-image-97717" alt="Elegance in Databases: The Art of SQL vs NoSQL"&gt;
      &lt;br&gt;
      &lt;br&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-8ee2faf elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container" style="font-size: 18px;"&gt; 
      &lt;p style="font-size: 16px;"&gt;6. &lt;strong&gt;Data Duplication: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;One of the main features of DynamoDB is the ability to duplicate data, which significantly enhances query performance and response times. However, data duplication increases storage costs, but AWS never charges for storage and only charges for write and read operations. However, while data duplication improves efficiency significantly, it also has drawbacks. Every change must be propagated across all duplicates, increasing the number of write operations that AWS charges for.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;When to Choose PostgreSQL or DynamoDB?&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Choose Postgresql&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li&gt;&lt;strong&gt;Complex Queries and Joins are Necessary: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Though join operations are sometimes costlier. PostgreSQL excels with complicated queries and joins, allowing you to quickly access and manage relevant data from numerous tables. Here is an example operations of join query&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td&gt;&lt;strong&gt;SELECT customers.name, SUM(orders.amount) FROM customers JOIN orders ON customers.id = orders.customer_id GROUP BY customers.name;&lt;/strong&gt;&lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;br&gt;2.&lt;strong&gt; Extensive Analytical and Reporting Needs: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If your application needs heavy analytical reports postgresql should be the go to databases as it can handle extensive queries and also reporting data&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;3. &lt;strong&gt;Data Integrity and Consistency : &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;Foreign keys, unique constraints, and check constraints are among PostgreSQL’s several data integrity capabilities, helping in the maintenance of consistent and correct data.&lt;/span&gt;&lt;/p&gt; 
      &lt;table&gt; 
       &lt;tbody&gt; 
        &lt;tr&gt; 
         &lt;td&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;CREATE TABLE products&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;( product_id SERIAL PRIMARY KEY,&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;name VARCHAR(100) NOT NULL,&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;price NUMERIC CHECK (price &amp;gt; 0),&amp;nbsp;&lt;/strong&gt;&lt;/p&gt; &lt;p style="font-size: 14px;"&gt;&lt;strong&gt;&amp;nbsp;stock INT CHECK (stock &amp;gt;= 0) );&lt;/strong&gt;&lt;/p&gt; &lt;/td&gt; 
        &lt;/tr&gt; 
       &lt;/tbody&gt; 
      &lt;/table&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;span style="font-size: 16px;"&gt;Using constraints to enforce data integrity.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 18px;"&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Choose DynamoDB&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li&gt;&lt;strong&gt;Scalability and Performance are Top Priorities: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB’s seamless scalability and flexibility to manage heavy traffic make it ideal for applications with varying or enormous workloads.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Faster Response: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;If one’s access patterns are defined and you designed your database efficiently DynamoDB will always retrieve data faster than SQL regardless of the data volume it will always fetch data faster.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;Flexible Data Models and Schema-less Design: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;DynamoDB’s schema-less design enables flexible data modeling, accepting various data structures without specified schema.&lt;/span&gt;&lt;/li&gt; 
       &lt;li&gt;&lt;strong&gt;High Availability and Fault Tolerance: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;&amp;nbsp;DynamoDB’s multi-region, multi-active architecture provides high availability and fault tolerance, ensuring that your application remains available even in the face of regional outages.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Scenario&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;strong&gt;Restaurant Management System&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;Consider a restaurant management system: customers go through the menus and and according to the menu they place orders and waiters serve the orders.In that case the following requirements are necessary&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Requirements:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Complex queries and joins for reporting.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;High data integrity and consistency.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Scalability for handling variable traffic.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Low-latency read and write operations.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;strong&gt;Probable Access Pattern:&lt;/strong&gt;&lt;/p&gt; 
      &lt;ol style="font-size: 16px;"&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Get all the menu&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Add an order&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Daily/monthly/yearly total order quantity/amount&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;strong&gt;Recommendation&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt;&lt;/p&gt; 
      &lt;ul&gt; 
       &lt;li&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;Postgresql: &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;It can be used for complex queries and joins operations for reporting purposes. Also any type of OLAP operations like how many orders for a particular time or over a period of time or how much sales generates over a period of time.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;span style="font-size: 16px;"&gt;&lt;strong&gt;DynamoDB&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: It can be used for faster read and write operations, for example retrieving all the menu items from the menu or adding an order. As these operations need faster response and also it can be used for variable traffic like when more users are entering the menu item or add in an order it should automatically scale up or down depending on the situations.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p style="font-size: 16px;"&gt;&lt;span style="font-weight: 400;"&gt;PostgreSQL and DynamoDB are both powerful database systems, with unique advantages based on your application’s requirements. PostgreSQL excels in handling complicated queries, transactions, and relational data models, making it ideal for traditional corporate applications and data warehousing. DynamoDB, on the other hand, provides seamless scalability, faster query response, low latency performance, and flexible data modeling, making it perfect for contemporary, high-traffic applications, IoT systems, and real-time analytics.&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;By evaluating your application’s specific needs around data structure, scalability, performance, and integration requirements with other AWS services, you can make an informed decision between PostgreSQL and DynamoDB. Both databases offer robust solutions to effectively manage and scale your data infrastructure, ensuring optimal performance and reliability for your application.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Felegance-in-databases-the-art-of-sql-vs-nosql&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>Blog</category>
      <category>DynamoDB</category>
      <pubDate>Tue, 04 Mar 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/elegance-in-databases-the-art-of-sql-vs-nosql</guid>
      <dc:date>2025-03-04T18:00:00Z</dc:date>
      <dc:creator>Foisal Reza</dc:creator>
    </item>
    <item>
      <title>Building End-to-End Live Streaming Solution with AWS Media Services - Best Software Development Team Extension Partner for Nordics</title>
      <link>https://www.craftsmensoftware.com/blog/building-end-to-end-live-streaming-solution-with-aws-media-services</link>
      <description>&lt;div class="hs-featured-image-wrapper"&gt; 
 &lt;a href="https://www.craftsmensoftware.com/blog/building-end-to-end-live-streaming-solution-with-aws-media-services" title="" class="hs-featured-image-link"&gt; &lt;img src="https://www.craftsmensoftware.com/hubfs/Imported_Blog_Media/62-End-to-end-Live-streaming-Solution-01.png" alt="Building End-to-End Live Streaming Solution with AWS Media Services - Best Software Development Team Extension Partner for Nordics" class="hs-featured-image" style="width:auto !important; max-width:50%; float:left; margin:0 15px 15px 0;"&gt; &lt;/a&gt; 
&lt;/div&gt; 
&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96702"&gt; 
  &lt;div class="elementor-element elementor-element-3cc58180 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-56c658b1 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Introduction&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In today’s digital age, live streaming has become a powerful tool for businesses, content creators, and broadcasters. Whether it’s for entertainment, education, or corporate communications, delivering high-quality live video to a global audience is more accessible than ever, thanks to cloud-based services like AWS Media Services. In this blog, I’ll walk you through the process of building a live streaming solution using AWS Media Services, starting from capturing video with a webcam to delivering it to viewers through a Content Delivery Network (CDN).&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Why AWS Media Services?&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Before diving into the walkthrough, let’s quickly review why AWS Media Services is a great choice for building live streaming solutions. AWS Media Services offer a comprehensive set of tools that allow you to ingest, process, package, and distribute live video with high performance and scalability. The services work seamlessly together, providing a reliable pipeline for live video streaming from start to finish.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Overview of the Process&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s a step-by-step overview of what we’ll be doing:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Capture video using a webcam and transmit it using FFmpeg.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Ingest the video stream with AWS Elemental MediaConnect.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Process the video stream with AWS Elemental MediaLive.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Package the processed video for delivery with AWS Elemental MediaPackage.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Deliver the video to viewers through Amazon CloudFront.&lt;/strong&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-3572568 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-19edad1 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s get started!&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 1: Capturing and Transmitting Video Using FFmpeg&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To begin, we need to capture video from a webcam and transmit it to AWS. For this, we’ll use FFmpeg, a versatile tool for handling multimedia data.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Install FFmpeg&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: First, download and install FFmpeg on your local machine. This tool will be used to capture the video feed from your webcam and send it to AWS.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You can verify the installation by opening a &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;bash&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; terminal inside the FFmpeg folder and running the following command:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9e3a4ca elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This will display the FFmpeg version if it has been installed correctly.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Identify Video and Audio Sources&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Once FFmpeg is installed, identify your webcam and microphone sources. You’ll need this information to configure FFmpeg properly. You can list all available devices using the following FFmpeg command:&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-45e802c elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt;
         &amp;nbsp; 
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-914b1d7 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
       &amp;nbsp; 
      &lt;span style="background-color: transparent; font-size: 1rem;"&gt;&amp;nbsp;&lt;/span&gt; 
      &lt;span style="background-color: transparent; font-size: 1rem;"&gt;&amp;nbsp;&lt;/span&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d4089f4 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;Transmit Video Using FFmpeg&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: With the sources identified, you can now use FFmpeg to transmit the video. Here’s the command:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;Replace &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YourWebcamName&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YourMicrophoneName&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; with the names of your devices, and &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YOUR_MEDIA_CONNECT_IP:PORT&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; with the IP address and port provided by AWS MediaConnect (in step 2).&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c0f6fb5 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Step 2: Ingesting Video with AWS Elemental MediaConnect&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaConnect is responsible for ingesting the video stream and forwarding it to other AWS services for processing.&lt;/span&gt;&lt;/p&gt; 
      &lt;strong&gt;1. Create a MediaConnect Flow&lt;/strong&gt; 
      &lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
      &lt;br&gt; 
      &lt;ul&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the AWS Management Console, navigate to &lt;/span&gt;&lt;strong&gt;AWS MediaConnect&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and create a new flow.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Select the source type as &lt;/span&gt;&lt;strong&gt;Standard Source&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, as the video will be coming from your local machine.&lt;/span&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;strong&gt;2. Configure the Flow&lt;/strong&gt; 
      &lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
      &lt;br&gt; 
      &lt;ol&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the protocol to &lt;/span&gt;&lt;strong&gt;SRT-Listener&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and specify the inbound port number (e.g., &lt;/span&gt;&lt;strong&gt;3000&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;).&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;For this demo, set &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;0.0.0.0/0&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; in the allowlist (CICD block).&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Create the flow. AWS will provide an &lt;/span&gt;&lt;strong&gt;inbound IP address and port&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which will be used in your FFmpeg command (refer to Step 1.4). &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;strong&gt;3. Run the FFmpeg Command&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Replace &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YOUR_MEDIA_CONNECT_IP:PORT&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; in the FFmpeg command with the provided &lt;/span&gt;&lt;strong&gt;Inbound IP:Port&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Run the command to start sending the video stream to MediaConnect.&lt;/span&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;strong&gt;4. Start the Flow&lt;/strong&gt; 
      &lt;span style="font-weight: 400;"&gt;:&lt;/span&gt; 
      &lt;br&gt; 
      &lt;ul&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start the MediaConnect flow and ensure the FFmpeg command is running.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;This will initiate the video stream from FFmpeg to MediaConnect. Verify that the &lt;/span&gt;&lt;strong&gt;health status&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; of the flow shows as &lt;/span&gt;&lt;strong&gt;connected&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ul&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-65b2def elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-bed70c3 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: While the MediaConnect flow typically sends video to AWS MediaLive for processing, and MediaLive then sends its output to MediaPackage, we’ll create the MediaPackage channel first since its endpoints are required during the MediaLive channel setup.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 3: Packaging Video with AWS Elemental MediaPackage&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaPackage packages the processed video into formats suitable for delivery to end-user devices.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a MediaPackage Channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Go to the AWS MediaPackage console and create a new channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Provide the necessary information, such as the &lt;/span&gt;&lt;strong&gt;channel ID&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;description&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and enable &lt;/span&gt;&lt;strong&gt;logging&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once completed, create the channel.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;HLS Ingest Endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;MediaPackage will automatically generate two &lt;/span&gt;&lt;strong&gt;HLS ingest endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, each with a unique &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;username&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and &lt;/span&gt;&lt;strong&gt;password&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;These credentials will be required when configuring your MediaLive channel (refer to Step 4 in the MediaLive setup).&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create an Origin Endpoint&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Navigate to the &lt;/span&gt;&lt;strong&gt;“Manage Endpoints”&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section in the MediaPackage console and create a new origin endpoint.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Provide an &lt;/span&gt;&lt;strong&gt;ID&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; for the endpoint and leave the other fields set to their default values.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once created, this origin endpoint will serve as the &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; where viewers can access the video stream.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Step 4: Processing Video with AWS Elemental MediaLive&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaLive is used to process the live video stream, enabling broadcast-quality video processing in real-time.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a MediaLive Channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Navigate to AWS MediaLive and create a new channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start with a predefined channel template, such as &lt;/span&gt;&lt;strong&gt;HTTP Live Streaming (HLS)&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and ensure you select the proper IAM role.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the channel class to &lt;/span&gt;&lt;strong&gt;SINGLE_PIPELINE&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which means only one stream will be processed.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Set Up Input Attachments&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the channel configuration, add an &lt;/span&gt;&lt;strong&gt;input attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and set the input type to &lt;/span&gt;&lt;strong&gt;MediaConnect&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, as your video stream originates from there.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the input class to &lt;/span&gt;&lt;strong&gt;SINGLE_INPUT&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and attach the previously created &lt;/span&gt;&lt;strong&gt;MediaConnect flow ARN&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once the input is created, return to &lt;/span&gt;&lt;strong&gt;add input attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and refresh inputs to attach the newly created input to the channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Additionally, create and name an &lt;/span&gt;&lt;strong&gt;audio selector&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; under &lt;/span&gt;&lt;strong&gt;General Input Settings&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Configure Outputs&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the &lt;/span&gt;&lt;strong&gt;HLS output group&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, remove all default outputs except &lt;/span&gt;&lt;strong&gt;output_1&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;strong&gt;output_2 &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;for this demo.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Use the &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;username&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and &lt;/span&gt;&lt;strong&gt;password&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; from the &lt;/span&gt;&lt;strong&gt;HLS ingest endpoint&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; of the MediaPackage channel (created in Step 3) in the &lt;/span&gt;&lt;strong&gt;HLS group destination&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. Provide a name and copied &lt;/span&gt;&lt;strong&gt;password &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;while creating the parameter.These credentials will be used to send the output to MediaPackage.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In &lt;/span&gt;&lt;strong&gt;output_1&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;strong&gt;output_2&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, select the audio selector created earlier in the &lt;/span&gt;&lt;strong&gt;Input Attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create and Start the channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once all the steps are completed, create the MediaLive channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start the channel and wait for the channel state to change to &lt;/span&gt;&lt;strong&gt;Running&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Check the &lt;/span&gt;&lt;strong&gt;preview section&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; to confirm the live stream is running successfully.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-beb2ff8 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;&lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-21ef64f elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You can also view the live stream by navigating to the &lt;/span&gt;&lt;strong&gt;preview link&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; under the &lt;/span&gt;&lt;strong&gt;Origin Endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section of the MediaPackage channel.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 5: Delivering Video with Amazon CloudFront&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Amazon CloudFront, a CDN service, delivers the video to viewers with high performance and low latency.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a CloudFront Distribution&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Go to the CloudFront console and create a new distribution. Select the MediaPackage origin you created earlier as the origin for this distribution.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Configure Distribution Settings&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Allow the necessary HTTP methods (GET, HEAD, OPTIONS) for the viewer, select CachingOptimized as cache policy, select “Do not enable security protections” for Web Application Firewall, and leave other settings as default for this demo.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Generate the Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: After creating distribution, CloudFront will provide a distribution domain name. Replace the domain part of the MediaPackage origin URL with this distribution domain name to generate the final streaming URL.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;For example:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Original MediaPackage URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://example.com/out/v1/stream/index.m3u8&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;CloudFront Distribution Domain&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://cdn.example.com&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Final Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://cdn.example.com/out/v1/stream/index.m3u8&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Test the Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Use a video player like VLC to open the final streaming URL. If everything is set up correctly, you should see the live video stream playing.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Voila! Now you should see your live stream video taken from your webcam, and using this URL, anyone can watch your livestream.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Building a live streaming solution with AWS Media Services is a powerful way to deliver high-quality video content to a global audience. By following these steps, you can create an end-to-end live streaming pipeline that captures video from a local webcam, processes it with AWS services, and delivers it through a CDN like CloudFront. This setup is scalable, reliable, and optimized for various network conditions, ensuring a smooth viewing experience for all your users.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Whether you’re a developer, content creator, or business looking to stream live video, AWS Media Services offers a comprehensive and flexible solution to meet your needs. With the right setup, you can deliver professional-grade live streams that engage and captivate your audience.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;</description>
      <content:encoded>&lt;div class="elementor-widget-container"&gt; 
 &lt;div class="elementor elementor-96702"&gt; 
  &lt;div class="elementor-element elementor-element-3cc58180 e-flex e-con-boxed wpr-particle-no wpr-jarallax-no wpr-parallax-no wpr-sticky-section-no e-con e-parent e-lazyloaded"&gt; 
   &lt;div class="e-con-inner"&gt; 
    &lt;div class="elementor-element elementor-element-56c658b1 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Introduction&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;In today’s digital age, live streaming has become a powerful tool for businesses, content creators, and broadcasters. Whether it’s for entertainment, education, or corporate communications, delivering high-quality live video to a global audience is more accessible than ever, thanks to cloud-based services like AWS Media Services. In this blog, I’ll walk you through the process of building a live streaming solution using AWS Media Services, starting from capturing video with a webcam to delivering it to viewers through a Content Delivery Network (CDN).&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Why AWS Media Services?&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Before diving into the walkthrough, let’s quickly review why AWS Media Services is a great choice for building live streaming solutions. AWS Media Services offer a comprehensive set of tools that allow you to ingest, process, package, and distribute live video with high performance and scalability. The services work seamlessly together, providing a reliable pipeline for live video streaming from start to finish.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;&lt;span style="font-weight: 400;"&gt;Overview of the Process&lt;/span&gt;&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Here’s a step-by-step overview of what we’ll be doing:&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Capture video using a webcam and transmit it using FFmpeg.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Ingest the video stream with AWS Elemental MediaConnect.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Process the video stream with AWS Elemental MediaLive.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Package the processed video for delivery with AWS Elemental MediaPackage.&lt;/strong&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Deliver the video to viewers through Amazon CloudFront.&lt;/strong&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-3572568 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="621" height="248" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image3-3.png?width=621&amp;amp;height=248&amp;amp;name=image3-3.png" class="attachment-large size-large wp-image-97637" alt="End-to-End Live Streaming with AWS Media Services"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-19edad1 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Let’s get started!&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 1: Capturing and Transmitting Video Using FFmpeg&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;To begin, we need to capture video from a webcam and transmit it to AWS. For this, we’ll use FFmpeg, a versatile tool for handling multimedia data.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Install FFmpeg&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: First, download and install FFmpeg on your local machine. This tool will be used to capture the video feed from your webcam and send it to AWS.&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You can verify the installation by opening a &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;bash&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; terminal inside the FFmpeg folder and running the following command:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-9e3a4ca elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;This will display the FFmpeg version if it has been installed correctly.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Identify Video and Audio Sources&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Once FFmpeg is installed, identify your webcam and microphone sources. You’ll need this information to configure FFmpeg properly. You can list all available devices using the following FFmpeg command:&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-45e802c elementor-widget elementor-widget-code-highlight"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;div class="prismjs-tomorrow copy-to-clipboard"&gt; 
       &lt;div class="code-toolbar"&gt;
        &amp;nbsp;
       &lt;/div&gt; 
      &lt;/div&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-914b1d7 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &amp;nbsp;
      &lt;span style="background-color: transparent; font-size: 1rem;"&gt;&amp;nbsp;&lt;/span&gt;
      &lt;img src="https://www.craftsmensoftware.com/wp-content/uploads/2025/02/image4.png" style="background-color: transparent; font-size: 1rem;"&gt;
      &lt;span style="background-color: transparent; font-size: 1rem;"&gt;&amp;nbsp;&lt;/span&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-d4089f4 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&lt;strong&gt;Transmit Video Using FFmpeg&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: With the sources identified, you can now use FFmpeg to transmit the video. Here’s the command:&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;Replace &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YourWebcamName&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YourMicrophoneName&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; with the names of your devices, and &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YOUR_MEDIA_CONNECT_IP:PORT&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; with the IP address and port provided by AWS MediaConnect (in step 2).&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-c0f6fb5 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;h2&gt;Step 2: Ingesting Video with AWS Elemental MediaConnect&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaConnect is responsible for ingesting the video stream and forwarding it to other AWS services for processing.&lt;/span&gt;&lt;/p&gt; 
      &lt;strong&gt;1. Create a MediaConnect Flow&lt;/strong&gt;
      &lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt;
      &lt;br&gt; 
      &lt;ul&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the AWS Management Console, navigate to &lt;/span&gt;&lt;strong&gt;AWS MediaConnect&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and create a new flow.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Select the source type as &lt;/span&gt;&lt;strong&gt;Standard Source&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, as the video will be coming from your local machine.&lt;/span&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ul&gt; 
      &lt;strong&gt;2. Configure the Flow&lt;/strong&gt;
      &lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt;
      &lt;br&gt; 
      &lt;ol&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the protocol to &lt;/span&gt;&lt;strong&gt;SRT-Listener&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and specify the inbound port number (e.g., &lt;/span&gt;&lt;strong&gt;3000&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;).&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;For this demo, set &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;0.0.0.0/0&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; in the allowlist (CICD block).&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Create the flow. AWS will provide an &lt;/span&gt;&lt;strong&gt;inbound IP address and port&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which will be used in your FFmpeg command (refer to Step 1.4). &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;strong&gt;3. Run the FFmpeg Command&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Replace &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;YOUR_MEDIA_CONNECT_IP:PORT&lt;/span&gt;&lt;span style="font-weight: 400;"&gt; in the FFmpeg command with the provided &lt;/span&gt;&lt;strong&gt;Inbound IP:Port&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Run the command to start sending the video stream to MediaConnect.&lt;/span&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;strong&gt;4. Start the Flow&lt;/strong&gt;
      &lt;span style="font-weight: 400;"&gt;:&lt;/span&gt;
      &lt;br&gt; 
      &lt;ul&gt; 
       &lt;li style="list-style-type: none;"&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start the MediaConnect flow and ensure the FFmpeg command is running.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;This will initiate the video stream from FFmpeg to MediaConnect. Verify that the &lt;/span&gt;&lt;strong&gt;health status&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; of the flow shows as &lt;/span&gt;&lt;strong&gt;connected&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ul&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-65b2def elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="188" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image1-1024x188.png?width=1024&amp;amp;height=188&amp;amp;name=image1-1024x188.png" class="attachment-large size-large wp-image-97639" alt="End-to-End Live Streaming with AWS Media Services"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-bed70c3 elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: While the MediaConnect flow typically sends video to AWS MediaLive for processing, and MediaLive then sends its output to MediaPackage, we’ll create the MediaPackage channel first since its endpoints are required during the MediaLive channel setup.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 3: Packaging Video with AWS Elemental MediaPackage&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaPackage packages the processed video into formats suitable for delivery to end-user devices.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a MediaPackage Channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Go to the AWS MediaPackage console and create a new channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Provide the necessary information, such as the &lt;/span&gt;&lt;strong&gt;channel ID&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;description&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and enable &lt;/span&gt;&lt;strong&gt;logging&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once completed, create the channel.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;HLS Ingest Endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;MediaPackage will automatically generate two &lt;/span&gt;&lt;strong&gt;HLS ingest endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, each with a unique &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;username&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and &lt;/span&gt;&lt;strong&gt;password&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;These credentials will be required when configuring your MediaLive channel (refer to Step 4 in the MediaLive setup).&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create an Origin Endpoint&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Navigate to the &lt;/span&gt;&lt;strong&gt;“Manage Endpoints”&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section in the MediaPackage console and create a new origin endpoint.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Provide an &lt;/span&gt;&lt;strong&gt;ID&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; for the endpoint and leave the other fields set to their default values.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once created, this origin endpoint will serve as the &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; where viewers can access the video stream.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;h2&gt;Step 4: Processing Video with AWS Elemental MediaLive&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;AWS Elemental MediaLive is used to process the live video stream, enabling broadcast-quality video processing in real-time.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a MediaLive Channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Navigate to AWS MediaLive and create a new channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start with a predefined channel template, such as &lt;/span&gt;&lt;strong&gt;HTTP Live Streaming (HLS)&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and ensure you select the proper IAM role.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the channel class to &lt;/span&gt;&lt;strong&gt;SINGLE_PIPELINE&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, which means only one stream will be processed.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Set Up Input Attachments&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the channel configuration, add an &lt;/span&gt;&lt;strong&gt;input attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and set the input type to &lt;/span&gt;&lt;strong&gt;MediaConnect&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, as your video stream originates from there.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Set the input class to &lt;/span&gt;&lt;strong&gt;SINGLE_INPUT&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and attach the previously created &lt;/span&gt;&lt;strong&gt;MediaConnect flow ARN&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once the input is created, return to &lt;/span&gt;&lt;strong&gt;add input attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and refresh inputs to attach the newly created input to the channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Additionally, create and name an &lt;/span&gt;&lt;strong&gt;audio selector&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; under &lt;/span&gt;&lt;strong&gt;General Input Settings&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Configure Outputs&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In the &lt;/span&gt;&lt;strong&gt;HLS output group&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, remove all default outputs except &lt;/span&gt;&lt;strong&gt;output_1&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;strong&gt;output_2 &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;for this demo.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Use the &lt;/span&gt;&lt;strong&gt;URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, &lt;/span&gt;&lt;strong&gt;username&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, and &lt;/span&gt;&lt;strong&gt;password&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; from the &lt;/span&gt;&lt;strong&gt;HLS ingest endpoint&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; of the MediaPackage channel (created in Step 3) in the &lt;/span&gt;&lt;strong&gt;HLS group destination&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;. Provide a name and copied &lt;/span&gt;&lt;strong&gt;password &lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;while creating the parameter.These credentials will be used to send the output to MediaPackage.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;In &lt;/span&gt;&lt;strong&gt;output_1&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; and &lt;/span&gt;&lt;strong&gt;output_2&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;, select the audio selector created earlier in the &lt;/span&gt;&lt;strong&gt;Input Attachment&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create and Start the channel&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;:&amp;nbsp;&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Once all the steps are completed, create the MediaLive channel.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Start the channel and wait for the channel state to change to &lt;/span&gt;&lt;strong&gt;Running&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;.&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;span style="font-weight: 400;"&gt;Check the &lt;/span&gt;&lt;strong&gt;preview section&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; to confirm the live stream is running successfully.&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
      &lt;/ol&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-beb2ff8 elementor-widget elementor-widget-image"&gt; 
     &lt;div class="elementor-widget-container"&gt;
      &lt;img width="1024" height="415" src="https://www.craftsmensoftware.com/hs-fs/hubfs/Imported_Blog_Media/image2-1024x415.png?width=1024&amp;amp;height=415&amp;amp;name=image2-1024x415.png" class="attachment-large size-large wp-image-97640" alt="Live Streaming Solution using AWS Media Services"&gt;
     &lt;/div&gt; 
    &lt;/div&gt; 
    &lt;div class="elementor-element elementor-element-21ef64f elementor-widget elementor-widget-text-editor"&gt; 
     &lt;div class="elementor-widget-container"&gt; 
      &lt;p&gt;&amp;nbsp;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;You can also view the live stream by navigating to the &lt;/span&gt;&lt;strong&gt;preview link&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; under the &lt;/span&gt;&lt;strong&gt;Origin Endpoints&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt; section of the MediaPackage channel.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Step 5: Delivering Video with Amazon CloudFront&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Amazon CloudFront, a CDN service, delivers the video to viewers with high performance and low latency.&lt;/span&gt;&lt;/p&gt; 
      &lt;ol&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Create a CloudFront Distribution&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Go to the CloudFront console and create a new distribution. Select the MediaPackage origin you created earlier as the origin for this distribution.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Configure Distribution Settings&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Allow the necessary HTTP methods (GET, HEAD, OPTIONS) for the viewer, select CachingOptimized as cache policy, select “Do not enable security protections” for Web Application Firewall, and leave other settings as default for this demo.&lt;/span&gt;&lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Generate the Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: After creating distribution, CloudFront will provide a distribution domain name. Replace the domain part of the MediaPackage origin URL with this distribution domain name to generate the final streaming URL.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;For example:&lt;/span&gt; 
        &lt;ul&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Original MediaPackage URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://example.com/out/v1/stream/index.m3u8&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;CloudFront Distribution Domain&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://cdn.example.com&lt;/span&gt;&lt;/li&gt; 
         &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Final Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: &lt;/span&gt;&lt;span style="font-weight: 400;"&gt;https://cdn.example.com/out/v1/stream/index.m3u8&lt;/span&gt;&lt;/li&gt; 
        &lt;/ul&gt; &lt;/li&gt; 
       &lt;li style="font-weight: 400;"&gt;&lt;strong&gt;Test the Streaming URL&lt;/strong&gt;&lt;span style="font-weight: 400;"&gt;: Use a video player like VLC to open the final streaming URL. If everything is set up correctly, you should see the live video stream playing.&lt;/span&gt;&lt;span style="font-weight: 400;"&gt;&lt;br&gt;&lt;br&gt;&lt;/span&gt;&lt;/li&gt; 
      &lt;/ol&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Voila! Now you should see your live stream video taken from your webcam, and using this URL, anyone can watch your livestream.&lt;/span&gt;&lt;/p&gt; 
      &lt;h2&gt;Conclusion&lt;/h2&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Building a live streaming solution with AWS Media Services is a powerful way to deliver high-quality video content to a global audience. By following these steps, you can create an end-to-end live streaming pipeline that captures video from a local webcam, processes it with AWS services, and delivers it through a CDN like CloudFront. This setup is scalable, reliable, and optimized for various network conditions, ensuring a smooth viewing experience for all your users.&lt;/span&gt;&lt;/p&gt; 
      &lt;p&gt;&lt;span style="font-weight: 400;"&gt;Whether you’re a developer, content creator, or business looking to stream live video, AWS Media Services offers a comprehensive and flexible solution to meet your needs. With the right setup, you can deliver professional-grade live streams that engage and captivate your audience.&lt;/span&gt;&lt;/p&gt; 
     &lt;/div&gt; 
    &lt;/div&gt; 
   &lt;/div&gt; 
  &lt;/div&gt; 
 &lt;/div&gt; 
&lt;/div&gt;  
&lt;img src="https://track-eu1.hubspot.com/__ptq.gif?a=144957314&amp;amp;k=14&amp;amp;r=https%3A%2F%2Fwww.craftsmensoftware.com%2Fblog%2Fbuilding-end-to-end-live-streaming-solution-with-aws-media-services&amp;amp;bu=https%253A%252F%252Fwww.craftsmensoftware.com%252Fblog&amp;amp;bvt=rss" alt="" width="1" height="1" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important; "&gt;</content:encoded>
      <category>AWS</category>
      <pubDate>Mon, 24 Feb 2025 18:00:00 GMT</pubDate>
      <guid>https://www.craftsmensoftware.com/blog/building-end-to-end-live-streaming-solution-with-aws-media-services</guid>
      <dc:date>2025-02-24T18:00:00Z</dc:date>
      <dc:creator>Omor Faruk Rakib</dc:creator>
    </item>
  </channel>
</rss>
