<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Kayode Adeniyi - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Kayode Adeniyi - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 04:42:34 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/mkbadeniyi/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How to Use Granular Segmentation with Feature Flags ]]>
                </title>
                <description>
                    <![CDATA[ These days, SaaS has become an integral part of running many businesses. So rolling out new features that resonate with the user base is key to a business’s growth. Imagine a feature that promises to enhance user experience but that ends up resonatin... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-granular-segmentation-with-feature-flags/</link>
                <guid isPermaLink="false">6793a744fc2bd29e0ece1253</guid>
                
                    <category>
                        <![CDATA[ SaaS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ user experience ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kayode Adeniyi ]]>
                </dc:creator>
                <pubDate>Fri, 24 Jan 2025 14:44:20 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1737681693640/2cd6aa99-94bf-48c6-b657-4cc0743312e3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>These days, SaaS has become an integral part of running many businesses. So rolling out new features that resonate with the user base is key to a business’s growth.</p>
<p>Imagine a feature that promises to enhance user experience but that ends up resonating with only a small subset of users. This scenario underscores the importance of precision in feature rollouts.</p>
<p>Fortunately, <a target="_blank" href="https://www.flagsmith.com/">feature flagging management tools</a> like Flagsmith can help with granular segmentation. This process helps your team make sure that new features are introduced to the most relevant audiences. Granular Segmentation makes it easier to understand your user base, leading to higher engagement and satisfaction.  </p>
<p>In this article, we will be focusing on the concept of granular user segmentation and its significance in enhancing feature rollouts. We’ll also explore some best practices, pitfalls to avoid, and will look at how Flagsmith facilitates granular segmentation with feature flags.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-is-flagsmith">What is Flagsmith?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-granular-segmentation">What is Granular Segmentation?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-feature-flags-enable-granular-segmentation">How Feature Flags Enable Granular Segmentation?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-granular-segmentation-in-flagsmith">How to Implement Granular Segmentation in Flagsmith</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-granular-segmentation-for-user-engagement">Benefits of Granular Segmentation for User Engagement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-is-flagsmith">What is Flagsmith?</h2>
<p>Flagsmith is an open-source feature management platform that helps teams control feature rollouts with precision. It helps developers toggle features on or off for specific users, environments, or groups without redeploying code.</p>
<p>Ideal for A/B testing, phased rollouts, and remote configuration, Flagsmith ensures real-time adjustments and seamless feature delivery. With flexible deployment options – hosted, private cloud, or on-premises – it adapts to the needs of organizations of all sizes.</p>
<h2 id="heading-the-importance-of-granular-segmentation"><strong>The Importance of Granular Segmentation</strong></h2>
<h3 id="heading-what-is-granular-segmentation"><strong>What is Granular Segmentation?</strong></h3>
<p>Granular segmentation is a process in which the user base is divided into groups based on unique attributes such as behavior demographics or engagement levels. These groups can be identified as segments of users of a platform, and each segment is based on several traits that help teams tailor feature rollouts to meet the needs of each segment.  </p>
<p>This granular level of control over rollouts helps product teams release features that resonate with their user base. This creates a more personalized experience for the end user that can improve the effectiveness of the feature. </p>
<p>Now, let’s discuss what kind of an impact feature rollouts might have. </p>
<h3 id="heading-impact-of-feature-rollouts"><strong>Impact of Feature Rollouts</strong></h3>
<p>The advantages of granular segmentation in feature rollouts include:</p>
<ul>
<li><p><strong>Targeted relevance:</strong> Features are delivered to users who will benefit most from them, making the updates more relevant and useful. This targeted approach increases the likelihood of user engagement.</p>
</li>
<li><p><strong>Optimized user experience:</strong> Because of this targeted approach, businesses can prevent rollouts of features that overwhelm their users in any way. This means that users would receive updates according to their interests, leading to a better user experience. </p>
</li>
<li><p><strong>Higher adoption rates:</strong> All this would also lead to higher adoption rates. An increased adoption rate is a sign of good engagement from a business’s users as well as of business growth</p>
</li>
<li><p><strong>Less risk when</strong> <strong>rolling out new features</strong>: Segmenting your user base and releasing new features to, say, a select 10% of users reduces risk. Teams can see how features do with those users and adjust accordingly before rolling out to the next segment. Or they can roll back if the impact is negative, which helps them avoid incidents like the latest high-publicity one we saw with CrowdStrike.</p>
</li>
</ul>
<p>To put things into perspective, let’s discuss an example of an e-commerce store. </p>
<h4 id="heading-the-mart-example"><strong>The MART Example</strong></h4>
<p>The MART is an online store that sells various products. They want to introduce an AI-powered recommendation engine, but only to a subset of their user base that shows less engagement on the platform buying products. AI-powered recommendation engines would target this user segment to generate more sales from the platform and increase business growth.</p>
<p>Here we see the concept of segmentation in practice where a feature is dedicatedly exposed to a user group's explicit attributes, thus leading to increased relevance and user satisfaction.</p>
<p>If the feature proves to be successful with the targeted segment, the next phase would be to expand its availability to other user groups.</p>
<h2 id="heading-how-feature-flags-enable-granular-segmentation"><strong>How Feature Flags Enable Granular Segmentation</strong></h2>
<p>You can integrate Flagsmith into your development workflow by using <a target="_blank" href="https://www.flagsmith.com/sdks">SDKs</a>. The user segmentation adds a layer of granular control to the product teams with over-feature releases. This control helps product teams to minimize the risk of degradation of a new feature. They can leverage the GUI to interact with Flagsmith and roll out/roll back features according to their needs.</p>
<h3 id="heading-what-are-segments-in-feature-rollouts"><strong>What are Segments in Feature Rollouts?</strong></h3>
<p>A segment is a subset of identities, defined by a set of rules based on traits associated with identities. So a single identity can be a part of many segments and is associated with an environment, such as staging or production.</p>
<p>You might be wondering – how can product teams use segments in their feature rollouts?</p>
<p>You can use segments to create ‘overrides’ on any number of features in your application. This allows you to control the state and/or value of a feature for a selection of your users, as defined by the segment.</p>
<p>Now that you understand segments, let’s discuss what key features allow you to use detailed user segmentation.</p>
<ul>
<li><p><strong>User attributes:</strong> Flagsmith allows you to define and manage user attributes, such as location, behavior, subscription levels, or platform activity. These are attributes you can use to create highly specific user segments.</p>
</li>
<li><p><strong>Segment definitions:</strong> You can create custom segment definitions from these user attributes. For instance, you can define a segment for users who have been highly active on the platform since last month or users who live in a different region than most of your user base. This granularity ensures that you can target features to the most relevant user groups.</p>
</li>
<li><p><strong>Dynamic targeting:</strong> Dynamic targeting can help you adjust feature rollouts on the basis of user attributes. This means that you can progressively roll out features to segments of users, monitor their performance, and make adjustments to the feature accordingly.</p>
</li>
</ul>
<h3 id="heading-flexibility-and-control"><strong>Flexibility and Control</strong></h3>
<p>Flexibility and control are a rare combination when it comes to such tools, but with Flagsmith you get the best of both worlds. User segments and feature management ensure you have precision and control over your feature rollouts:</p>
<ul>
<li><p><strong>Granular control:</strong> Multiple segment creation and control access are available in Flagsmith with a variety of criteria, allowing feature rollouts that cater to specific user needs.</p>
</li>
<li><p><strong>Analytics and feedback:</strong> Analytics and feedback are an integral part of the feature testing loop. They provide tracking of how different segments interact with new features. It’s invaluable for understanding the user’s behavior on the platform which helps you make informed decisions for further rollouts.</p>
</li>
</ul>
<p>So now you’ve learned what segments are, what you can do with them, and how segments help in granular control over rollouts. Now, let’s move on and see how you can implement segmentation using Flagsmith.</p>
<h2 id="heading-how-to-implement-granular-segmentation-in-flagsmith"><strong>How to Implement Granular Segmentation in Flagsmith</strong></h2>
<h3 id="heading-set-up-flagsmith-in-your-project"><strong>Set Up Flagsmith in Your Project</strong></h3>
<p>You can integrate Flagsmith into your application using the available SDKs for the language of your choice. For example, to integrate the SDK in Node.js, you’ll first need to install the npm package as follows:</p>
<pre><code class="lang-javascript">npm i flagsmith-nodejs --save
</code></pre>
<p>After installing the package, you will use the following code to initialize Flagsmith in your project:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> Flagsmith = <span class="hljs-built_in">require</span>(<span class="hljs-string">'flagsmith-nodejs'</span>);
<span class="hljs-keyword">const</span> flagsmith = <span class="hljs-keyword">new</span> Flagsmith({ <span class="hljs-attr">environmentKey</span>: <span class="hljs-string">'FLAGSMITH_SERVER_SIDE_ENVIRONMENT_KEY'</span>,});
</code></pre>
<p>Once it’s integrated, configure your Flagsmith instance by creating a new project. We’ll go through this below.</p>
<h3 id="heading-how-to-create-identities-and-define-user-traits-and-segments"><strong>How to Create Identities and Define User Traits and Segments</strong></h3>
<p>Now you’ll need to create the identities and traits you want to use for segmentation. These could include user profile information, behavior metrics, or any other relevant data.</p>
<p>So, let’s create a user named John Doe.</p>
<ul>
<li><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcorqiG6dhrwu_3IARs_A3Rgn39I_g_9_cGNEyawmu6SWwqOFCXm_vXm8VGbgDHSzo4LMnnlSQ7DgvE_1_EH_MLBta2_eGhlMSPfabjGR7YwFvTCq3lnBWdoQDdu16x5elbFWp6zGHgmBbpiqdD9PnK4Hgb?key=CLsy_98J-hXFutqrVNKvTw" alt="create new ID on Flagsmith" width="1600" height="703" loading="lazy"></li>
</ul>
<p>Now click on the created user and define a trait country.</p>
<p>In Flagsmith, creating a <em>trait country</em> involves defining a user attribute that specifies their geographic location. Traits are key-value pairs assigned to user identities, allowing for precise segmentation. For example, you can define the "country" trait with values like "USA," "Canada," or "Germany."</p>
<p>This enables product teams to create segments based on location and target feature rollouts accordingly. For instance, a feature can be activated only for users with the "country" trait set to "USA," facilitating controlled and region-specific rollouts.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfsPeipIa35FrYuK7UuEz4g_5wrnwVvlk1YiJs1nNNmWiwszZcSVmb7zfD8CpN81Vh6rxNasuZHk5ze6nFPmkIF4JxFDWmb1gU68hd0CoDbuN5pjOMAZyJnZTCQWwxJPigYeooK7AlC0Mwjte74S9F_PbY?key=CLsy_98J-hXFutqrVNKvTw" alt="Defining trait and country on flagsmith" width="1600" height="640" loading="lazy"></p>
<p>Next, you’ll create some segments. You’ll use the Flagsmith dashboard to create custom segments based on these attributes. For example, you can create a segment for users who are from the USA. Define your segment, for example (western_users ), as below:</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXdPPGFxPEnBJXEIXNkDGyuC3IJQfE2G4wEtsSWtinIm3Yg_evRmo_ly1_ZPwCqwuWojv7XYI2DP_MMXBQqQy80FFIrccL-KXdmsS9cTrz5T5f9485vDcfiZlH-wkKTZBrk9-Lt9hvKZJgA-3ugQbeoiSfRS?key=CLsy_98J-hXFutqrVNKvTw" alt="Define segments on flagmith" width="1600" height="640" loading="lazy"></p>
<h3 id="heading-how-to-create-and-manage-feature-flags"><strong>How to Create and Manage Feature Flags</strong></h3>
<p>Create a feature flag called ai_recommendation_engine in Flagsmith for the features you want to roll out. Each flag represents a specific feature or configuration option that can be toggled on or off.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXciWtuMzy24Sl_n-i8_lGigMUfbCbV5KdmlAqEotHQiVp7CIw7myLIsVTqltTmZp1STUkAdwNPhGB11PI5tvdHB9dp84x3mjI9rR6ycu7Z-nHYFPUddjBu2adQceVkW8YLvUj6s_tOVpNdA78z3-tL6X06U?key=CLsy_98J-hXFutqrVNKvTw" alt="Specific feature or configuration option on Flagsmith" width="1600" height="653" loading="lazy"></p>
<p>Next, assign your feature flags to the segment you created. For instance, if you have a recommendation engine, you can target it specifically to users that match the segment created in the previous step. Use the Flagsmith dashboard to set these targeting rules and manage feature flag settings.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXe4XKYMDUOMCrECTgvp9wK2I2j_HIvDBeDEr1EG0Nf3OdfxducIE-xiDn6GSPRi84veq2K2r0OnvPaCgyuO7xkRVWlpYLjXuJC5F7PS0rP-xzbUL52MO1fHl_E08wAXLsxI8JSLkZP4Q4_NMvrgPRl2OVUw?key=CLsy_98J-hXFutqrVNKvTw" alt="Setting up targetting rules on Flagsmith" width="1600" height="611" loading="lazy"></p>
<h3 id="heading-how-to-target-segments-for-rollouts"><strong>How to Target Segments for Rollouts</strong></h3>
<p>After configuring Flagsmith and setting up your segments and traits, you can start rolling out features to your defined segments.</p>
<p>First, you’ll want to do gradual rollouts. Using the percentage split operator, you can initially release the feature to a small percentage of users within the segment. Based on performance and feedback, you can gradually expand the rollout to a larger portion of the segment or additional segments, ensuring a controlled and data-driven approach.</p>
<p>Second, monitoring is a crucial part of feature rollouts and Flagsmith can help you with its analytics tools. You can track the performance of your feature flags and user segments, monitor how different segments interact with the new features, and make adjustments as needed.</p>
<p>For example, you might decide to increase the rollout percentage or adjust segment definitions based on user feedback.</p>
<h4 id="heading-some-best-practices">Some best practices:</h4>
<ul>
<li><p><strong>Start small:</strong> To test out segmentation, it’s a good idea to start small and create well-defined segments to test new features. This will help you gather valuable feedback and will prevent you from being overwhelmed in case of degraded performance or a rollback scenario.</p>
</li>
<li><p><strong>Use data:</strong> Analytical tools are a great help in gathering data on how different segments interact with your features. You can use this data to refine your targeting and improve the user experience.</p>
</li>
<li><p><strong>Iterate:</strong> You’ll likely make better decisions after several iterations. So remember that you should iterate your segmentation and rollouts based on metrics and user feedback.</p>
</li>
</ul>
<h4 id="heading-some-common-pitfalls">Some common pitfalls:</h4>
<ul>
<li><p><strong>Overlapping segments:</strong> Distinction between segmentations is the key to avoiding conflicts between feature targeting. Always be careful while defining segments for your user groups.</p>
</li>
<li><p><strong>Ignoring feedback:</strong> The greatest mistake a product team can make is to overlook early user feedback. Early feedback is crucial for identifying issues and making informed decisions about a feature rollout.</p>
</li>
</ul>
<p>By following these steps and best practices, you can effectively use this granular segmentation approach, ensuring that your feature rollouts are targeted, relevant, and successful.</p>
<h2 id="heading-benefits-of-granular-segmentation-for-user-engagement"><strong>Benefits of Granular Segmentation for User Engagement</strong></h2>
<h3 id="heading-improved-user-satisfaction"><strong>Improved User Satisfaction</strong></h3>
<p>Granular segmentation helps your users out, as it gives them specifically personalized features according to their needs and inclinations. You can build more personalized experiences by aiming certain features at particular users that match their behavior or interest.</p>
<p>For example, a fitness app might launch an update that contains a workout feature for those users who have shown interest in strength building, rather than for all users. This targeted approach ensures that users receive updates related to and suitable to them, which leads to a positive experience, increased satisfaction, and better recognition of your product.</p>
<h3 id="heading-increased-engagement"><strong>Increased Engagement</strong></h3>
<p>When users get features or updates that are targeted toward their specific needs, it’s more likely that they’ll engage with that feature. Granular segmentation helps maximize engagement by providing users with upgrades that are pertinent to their interests and usage patterns.</p>
<p>For example, an e-commerce platform could propose a new recommendation system and try it out on users who recurrently browse specific categories. This relevant targeting will likely increase the probability that those users will respond to those recommendations, leading to increased engagement and potentially higher conversions.</p>
<h3 id="heading-enhanced-feature-adoption"><strong>Enhanced Feature Adoption</strong></h3>
<p>Targeting specific segments of users with features that address their needs should lead to higher adoption rates. Presenting new features to users who are very likely to benefit from them, you increase the probability of these features being adopted and utilized.</p>
<p>For example, a software company introducing a new improved analytics tool would likely target power users who consistently use analytics features. After those users provide positive feedback and adopt the tool, it can be deployed on other segments. Then the team can be confident that the feature is approved and effective.</p>
<h3 id="heading-data-driven-insights"><strong>Data-Driven Insights</strong></h3>
<p>Granular segmentation offers valuable insights into how various user groups engage with new features. Analyzing this data can provide you insights into the behavior and inclinations your users as well as the overall impact of your features.</p>
<p>For example, you might realize that users are responsive to new features in a specific segment compared to other segments. Such information helps you refine your feature strategy, making rational decisions regarding future launches, and enhancing user engagement across different segments.</p>
<h3 id="heading-optimized-resource-allocation"><strong>Optimized Resource Allocation</strong></h3>
<p>Centering on targeted segments lets you allocate resources more effectively. instead of investing in a broad, one-size-fits-all approach, you can direct your initiative towards segments that are likely to benefit from and engage with new features. This optimized allocation assures that your resources are utilized efficiently, leading to positive outcomes and a higher return on investment.</p>
<p>By leveraging granular segmentation, you can enhance user engagement, improve feature adoption, and gain valuable insights, all of which contribute to a more successful and user-centric feature rollout strategy.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>In this article, we discussed the power of granular user segmentation in driving successful feature rollouts, highlighting how it can improve user satisfaction, engagement, and adoption rates. We also explored how Flagsmith enables this approach, offering tools to manage and target features with precision.</p>
<p>By leveraging these strategies, you can ensure that your product updates are more relevant and impactful. If you're interested in optimizing your feature rollouts, consider exploring Flagsmith’s capabilities to start making data-driven decisions.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How Feature Flags and Role-Based Access Control Can Help Secure Your DevOps Process ]]>
                </title>
                <description>
                    <![CDATA[ These days, software is being developed and deployed at a very rapid pace. It makes it easy to understand how the saying “move fast and break things” became commonplace.  In an era where agile development is the go-to practice for quick feature relea... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/feature-flags-and-role-based-access-control-devops/</link>
                <guid isPermaLink="false">66b9ef59148b506e83d90ab6</guid>
                
                    <category>
                        <![CDATA[ Devops ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kayode Adeniyi ]]>
                </dc:creator>
                <pubDate>Mon, 22 Apr 2024 21:26:27 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/04/pete-alexopoulos-IssFEVzKV1w-unsplash.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>These days, software is being developed and deployed at a very rapid pace. It makes it easy to understand how the saying “move fast and break things” became commonplace. </p>
<p>In an era where agile development is the go-to practice for quick feature releases and feedback, it's easy for security and compliance to get overlooked. This may be securing CI/CD pipelines, protecting user data, or managing access to feature flagging in production environments. </p>
<p>Though the tech industry is aware that strong security measures and compliance practices are essential in DevOps, sometimes these measures take a back seat behind the need to get code shipped to production.</p>
<p>Because of this, it's crucial that you understand the importance of security and compliance in DevOps. You should also learn how your team can leverage popular security concepts like Roll-Based Access Control (RBAC), which is what we'll focus on here. </p>
<p>This is useful not only for DevOps teams (as a compliant practice for assigning access to teams), but also as a full-fledged feature that SaaS platforms such as <a target="_blank" href="https://www.flagsmith.com">Flagsmith</a> (an open source feature flagging platform) provide to their customers.     </p>
<p>But you might ask – why is RBAC important? Well, we'll cover that and more in this tutorial.</p>
<h2 id="heading-table-of-contents">Table of Contents:</h2>
<ol>
<li><a class="post-section-overview" href="#heading-why-is-rbac-important">Why is RBAC Important?</a></li>
<li><a class="post-section-overview" href="#heading-feature-flagging-and-flagsmith">Feature Flagging and Flagsmith</a></li>
<li><a class="post-section-overview" href="#heading-understanding-users-groups-roles-and-permissions">Understanding Users, Groups, Roles, and Permissions</a><br>– <a class="post-section-overview" href="#heading-create-the-project">Create the project</a><br>– <a class="post-section-overview" href="#heading-create-the-group">Create the group</a><br>– <a class="post-section-overview" href="#heading-create-an-editor-role">Create an Editor role</a><br>– <a class="post-section-overview" href="#heading-assign-permissions-to-the-editor-role">Assign permissions to the Editor role</a><br>– <a class="post-section-overview" href="#heading-assign-the-editor-role-to-a-group">Assign the Editor role to a group</a><br>– <a class="post-section-overview" href="#heading-test-the-assigned-permissions">Test the assigned permissions</a></li>
<li><a class="post-section-overview" href="#heading-use-case-the-chaos-at-netglobal-solutions">Use Case: the Chaos at "NetGlobal Solutions"</a><br>– <a class="post-section-overview" href="#heading-how-to-mitigate-the-issue">How to mitigate the issue</a></li>
<li><a class="post-section-overview" href="#heading-how-to-establish-a-standard-devops-process">How to Establish a Standard DevOps Process</a></li>
<li><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></li>
</ol>
<h2 id="heading-why-is-rbac-important">Why is RBAC Important?</h2>
<p>Keeping it simple, role-based access control is a fundamental requirement for DevOps. If you don't implement RBAC, your user's data is at a much greater risk of compromise. This can lead to financial losses and damage to your site's reputation. </p>
<p>So to reduce the attack surface and avoid damages, DevOps teams should leverage all security mechanisms at hand, <a target="_blank" href="https://www.redhat.com/en/topics/security/what-is-role-based-access-control">such as RBAC</a>. RBAC is pretty much what it sounds like: giving people on a team permissions based on the role they play within the organization.</p>
<p>This helps secure not only the lifecycle of a feature released in production but also how it is managed after the release – should it be enabled or disabled? Which users should be able to use it? And who will be responsible for performing this operation? </p>
<p>This is where feature flagging and the need for a platform that manages these security concerns come into play.  </p>
<p>What is feature flagging anyway and why is RBAC important to manage it?</p>
<h2 id="heading-feature-flagging-and-flagsmith">Feature Flagging and Flagsmith</h2>
<p>Feature flagging is a software development concept that involves enabling or disabling a feature independent of redeploys or source code changes. </p>
<p><a target="_blank" href="https://www.martinfowler.com/articles/feature-toggles.html">Feature flags</a> are conditional statements in the application code that determine which section of code to execute on runtime based on a boolean value. They help deploy new features to production and provide granular control over their visibility to a user base or deployment environment.   </p>
<p>You can configure feature flag values by various methods, such as config files, request headers, or from the database. This means that there's a certain amount of necessary developer intervention in this process. And anyone with access to the code or database can enable or disable a feature in production. </p>
<p>Although companies have compliance practices to handle feature flagging, there is always a chance of someone doing something that could harm production (intentionally or unintentionally). </p>
<p>So, to give you and your team better visibility and fine-grained control over feature toggling, feature flagging tools such as Flagsmith help you address such security and permission issues. </p>
<p>But you might be wondering – how does Flagsmith manage permissions and users? Enter <strong><a target="_blank" href="https://www.flagsmith.com/role-based-access-change-control-security">RBAC</a></strong>, which is built into the Flagsmith toolset. This makes it easier for larger teams to collaborate across projects and environments, and for companies to manage access. Let's dive deeper to understand how it works.</p>
<h2 id="heading-understanding-users-groups-roles-and-permissions">Understanding Users, Groups, Roles, and Permissions</h2>
<p>Flagsmith has two primary roles in the RBAC system: organization administrator and simple users. </p>
<p>Organization administrators enjoy the privilege of having superuser capabilities, whereas regular users require explicit permission to access the needed resources. Flagsmith also lets you control permissions for numerous users in a group. This makes access management easier for larger teams that are divided up based on responsibilities.  </p>
<p>There are also certain roles in Flagsmith RBAC that can have a permission set attached to them. This enables people with these roles to access particular features of Flagsmith. </p>
<p>Roles come in handy especially when you need to assign bulk permissions to a group. In this case, you can create a role, assign permissions, and attach it to a group.   </p>
<p>If we look at permissions from a macro level, we can see that Flagsmith has divided the permission set into three different levels: Organization, Project, and Environment. </p>
<p>For instance, we can manage permission sets for users to create projects at the organizational level. At the project level we can get access to environment creation, audit logs, and feature and segment management. Lastly, we can manage feature flags, segments, identities, and more on the environment level.</p>
<p>Before we move on to a case study, let's create an arbitrary project on Flagsmith and give permissions to a user so they can start creating feature flags for the project. We will perform the following actions:</p>
<ul>
<li>Create a project inside an organization</li>
<li>Create a group “front_end_devs” and add users to this group</li>
<li>Create an editor role</li>
<li>Assign organization, project, and environment level permissions</li>
<li>Assign the role to the newly created group</li>
<li>Login in with the user account to test assigned permissions</li>
</ul>
<h3 id="heading-create-the-project">Create the Project</h3>
<p>Click on the Create Project button after logging in with an owner account. We'll name this project <strong>Dev Test.</strong> </p>
<p><img src="https://lh7-us.googleusercontent.com/Gk4FaR8EecQ2vlUipL3KiIVENZnQuEkTX9n0FL9szgQJuHzXuZEfduIQ2oYnDst46yc0zVAubcgq0i0L32Q12jNEsbcIQep9X_5sVde_tXgJ8OcCbOCZOHDm3ThruWbEHZBXo2E9G7hiE0CpJgfiECM" alt="Image" width="1600" height="793" loading="lazy">
<em>Create the project</em></p>
<h3 id="heading-create-the-group">Create the Group</h3>
<p>Navigate to the <strong>Members</strong> tab, click Create Group, then fill in the required details.</p>
<p><img src="https://lh7-us.googleusercontent.com/gGa6rP_qH9pyoOL0vh3T5euQfpDUq7gmoPGnEJfBzlynt8rc1vTmfErCfgidTZrLfVCMeMhor69wrJKzqdqZpOx_bC6T2Wp9hkCo93zZvXElCplrgpCT6k-n9N8jq6nd9Ov7cwK3bLPvVk3aPn7tpWs" alt="Image" width="1600" height="793" loading="lazy">
<em>Enter the information for creating a group</em></p>
<p>We created a group “<strong>front_end_devs</strong>” and made John Smith the group admin. Consider this as an inline permission while creating a group. John can now manage the users inside this group.</p>
<h3 id="heading-create-an-editor-role">Create an Editor Role</h3>
<p>Click on <strong>Roles</strong> next to <strong>Groups</strong>, and create a role called “<strong>Editor</strong>”.</p>
<p><img src="https://lh7-us.googleusercontent.com/5zlCc-KmGxUNu069Tv-WQeibL7P-gnAMnTO6JoswreHIAy-jZip4Ym5svznawtNQZIJS-Tkn6XiXyHi3hJehtGJN3QyOwzx82EMYF0WbpSo9kKawhcEroeKxoSkdNe9suxvIqmee9-JjPQFt1GCHbhw" alt="Image" width="1600" height="793" loading="lazy">
<em>Creating an editor role</em></p>
<p>We created the role called Editor, so now let’s assign the appropriate permissions to this role. The Editor will be given permissions at all three levels – Organization, Project, and Environment.</p>
<h3 id="heading-assign-permissions-to-the-editor-role">Assign Permissions to the Editor Role</h3>
<p>To assign permissions, click the name of the role you just created. You will see a sidebar on the right side with a permissions tab. We'll assign permissions for all levels, starting from the Organization level.</p>
<p><img src="https://lh7-us.googleusercontent.com/se3FjEfVwxJEAnOI2PZGFVcCUk9a1OhtUVWxnqOb2oPgwJV_m08fWZoHjanZkCUMqr_DFUHpIp4RTphmRBWAybeZpGX6asEKDIu8TD8LvQEnbSOkQhchMfygcdMwymQRV0DxSVjeS6y4YqUW7YmEJls" alt="Image" width="1600" height="793" loading="lazy">
<em>Assigning permissions starting at the Organization level</em></p>
<p>This Editor role can now create projects in this organization and manage the groups and their members in this organization.</p>
<p>Next, we give it Project level permissions. Click on the project name under the Project tab, and do as shown in the screenshot below:</p>
<p><img src="https://lh7-us.googleusercontent.com/WKCBnmjb_r458FNPXVt-7Lp9lAAJpwnl8q5YLXLU709HDMDa81b047oe-FPElWOz41Z5MwVP8wrO4LPXZYALEO2gc0p46lPhp9cp8yDJWYGzqb1KCs63Aq_dT57fIPEzM4ZOLe2N9-XbAfH61-7dRGE" alt="Image" width="1600" height="795" loading="lazy">
<em>Assigning project-level permissions</em></p>
<p>As you can see, we assigned this role two project-level permissions: <strong>View Project</strong>, and <strong>Create Feature</strong>. So any user or a set of users with this role will only be able to view a project and create a feature.</p>
<p>Now for the most granular permissions, which are at the environment level. Click on the Environment tab, choose the Dev Test project from the dropdown, and click on the Development Environment.</p>
<p><img src="https://lh7-us.googleusercontent.com/bX6kJwrSeL4EB_rfgwtF3FQlRFE3nqysci5BTEqwSS-i4ypmXUk4g2Dib1MrkMEsIjTYM8ClNT0y8NGa2p3-Q-R1afP4zvLuTtnN0NAoG9HXW8Vs2sx5tde44DJ9GuoaQX5Ucs6qdPZ5IY9plWWWScA" alt="Image" width="1600" height="793" loading="lazy">
<em>Handling Environment level permissions (the most granular)</em></p>
<p>As you can see, we assigned this role two environment-level permissions: <strong>View Environment</strong>, and <strong>Update Feature State.</strong> Any user or a set of users with this role will only be able to view an environment and update its feature state value in the project.</p>
<h3 id="heading-assign-the-editor-role-to-a-group">Assign the Editor Role to a Group</h3>
<p>Now we will assign this role to the “<strong>front_end_devs”</strong> group. To do this, select the editor role, go to the Members tab, then click the text “<strong>Assigned Groups</strong>”. Enter the name of your group in the search bar, and select it.</p>
<p><img src="https://lh7-us.googleusercontent.com/7-j0MWNj30Y4GEplEcCDKkuzrE4xBkwlckPvev5lMCHHWTwvyL6J6ulUNIiGTtREnWdkJIyi8PPa4ZAXFsjrxMadysh9-nmcT5rwJNux-14LCU-BP7gHhzJKMz75kY0yrFHCVZDqk9eklEYCSu7a_G4" alt="Image" width="1600" height="793" loading="lazy">
<em>Searching for groups to which to assign the Editor role</em></p>
<h3 id="heading-test-the-assigned-permissions">Test the Assigned Permissions</h3>
<p>After going through the above steps, users in the “<strong>front_end_devs”</strong> group should only be able to perform the following operations</p>
<ul>
<li>Create a new project and manage its groups (Organizational level). Being the creator of a new project, the policies assigned to that user for another project will not be applicable here.</li>
<li>Create and Delete Features in Dev Test Project</li>
<li>Update feature state values in the Dev Test Project </li>
</ul>
<p>Now we log in from John Smith’s account, a testing user from the “<strong>front_end_devs”</strong> group, to verify the assigned permissions are working properly. </p>
<p>First, we will check the organizational level permissions which lets us create a new project.</p>
<p><img src="https://lh7-us.googleusercontent.com/97YU-J_iusUdPt_IR5KrKrxHqIMsATZ559sUykWlS2q1M_o2RAsUKWkeZaONNc606gsc4rTltj5bvGRaIcN_xAPQmo7IYxms5K2mxOoOE5lyrg1_WuvDZ6oLUysj26EqVzrulBUcAkMfjgvFXUvDS6o" alt="Image" width="1600" height="818" loading="lazy">
<em>Checking organizational level permissions</em></p>
<p>You can see that the user was successfully able to create a new project. And since he is the creator of this project, John is the admin and has full authority to manage it. </p>
<p>Now we can test the permissions for the Dev Test project. Just click on the project name from the left-hand dropdown list and switch between projects. You will surely notice that in the left menu bar, you only have access to the development environment. This is due to the environment-level permissions we assigned to the Editor role. </p>
<p>To create the feature just click on the Create feature button, give the feature a name, and enter a value of your choice.</p>
<p><img src="https://lh7-us.googleusercontent.com/JgFC5AAlw_KJy6vnKARWlCkugkiy79k2mB4QxkpRfE37DOfozKYhuNpInPnG0c8tEm6Tum70_ImXIcOGEJsXPRdsbs_6sD9Y8U5U1PtAzVzWEemZf5XWU18i1U84DtLPUzV-Grlf0vrbOP_XfPudjGY" alt="Image" width="1600" height="821" loading="lazy">
<em>Creating a feature</em></p>
<p>You will see something like this after the feature creation:</p>
<p><img src="https://lh7-us.googleusercontent.com/-YVJ1FAeV5LUuBe6myfqcwFgE3FufIdU56-7RwE-wml4ZD4tVY9UrMUsVW-daXuiAfA7xsp7oDuM0fcboHLN-A9dGxan47wgbaNL5bb91Mk2cn80QIggoF3QWfUHPBzx7tD_KCkzYFaszjjfp3MrtnU" alt="Image" width="1600" height="821" loading="lazy">
_After creating the feature called <code>johns_feature</code>_</p>
<p>Now you should have a basic understanding of how Flagsmith’s RBAC handles permission assignments and manages users, groups, and roles. </p>
<p>To help you get a holistic view of things and understand how implementing Flagsmith for feature flagging can minimize chaotic incidents in production, let's consider a use case.</p>
<h2 id="heading-use-case-the-chaos-at-netglobal-solutions">Use case: The Chaos at “NetGlobal Solutions”</h2>
<p>Let's hypothesize that there's a company called NetGlobal Solutions, a global giant in the network industry. They provide various networking solutions to their customers, such as CDN, DNS management, geo-location, cloud cybersecurity, and DDoS mitigation.  </p>
<p>They decided to introduce a new service, NetGlobal load balancing (a solution to manage huge amounts of web traffic) for their customers. </p>
<p>NetGlobal policy dictates that a feature should be tested for at least 3 months with only 10% of their customers before fully exposing it to the rest of the users. So they decided to use feature flagging to test it in production with 10% of their customers – let's say 10,000 considering the large size of their customer base. </p>
<p>The feature flag values are passed down to their code base from a central database table isolated from any relationships with other tables. The table has a boolean value that manages the visibility of the new feature, and Devin, the team lead for developing this feature, is responsible for its management and stability.</p>
<p>So, the time comes and Devin releases the feature in production. Two months go by and thousands of customers are using their load balancing service for their projects. </p>
<p>A dev from Devin’s team, while working on the prod database, accidentally changes the feature flag value in the table. Due to this mistake, the load balancing service instantly goes down and users start to face traffic loss on their sites. </p>
<p>The monitoring system triggers an alarm and the dev and DevOps teams spring into action. In about 10-15 minutes, they find the problem and resolve the issue. But because the user base is huge and the usage of the feature at the user end was quite technical, an impactful loss already happened.</p>
<h3 id="heading-how-to-mitigate-the-issue">How to Mitigate the Issue</h3>
<p>Now, let's consider how Devin's team could've mitigated this incident if they'd been using Flagsmith to create feature flagging. We'll also look at how its RBAC would have helped to secure the flag value access.</p>
<ul>
<li><strong>Flag value management:</strong> By using <a target="_blank" href="https://www.flagsmith.com/sdks">Flagsmith’s SDK</a> in the application code, the flag values could have been managed and passed to the application with clear visibility. </li>
<li><strong>Audit control:</strong> By using Flagsmith’s audit log, the team could've had better accountability and transparency concerning changes made to feature flags.</li>
<li><strong>RBAC:</strong> it would have restricted access to unauthorized developers so that they couldn't change the feature flag values and provided granular control to the team lead, release managers, or DevOps engineers.</li>
</ul>
<p>This hypothetical use case helps us get a basic understanding of the significance of a feature flagging tool for production releases. It also shows us why RBAC plays an important role in managing permissions and hierarchy in an ecosystem to help your team avoid downtime incidents. </p>
<p>The key takeaway here is that it's important to establish a standard DevOps process and choose DevOps tools that become a compliant part of feature release and management.</p>
<h2 id="heading-how-to-establish-a-standard-devops-process">How to Establish a Standard DevOps Process</h2>
<p>A standard DevOps process should be set in place for the lifecycle of a feature. It should address all the steps from the build stage to the production release. </p>
<p>Most importantly, in the pursuit of quick releases, your team shouldn't ignore the importance of securing this process as I mentioned at the beginning of this article.   </p>
<p>A basic example of a standard DevOps process would start with establishing a strong <strong>Continuous Integration workflow</strong> with the following steps:</p>
<ol>
<li><strong>Build and Scan:</strong> Building artifacts and vulnerability scanning before pushing to artifact hubs.</li>
<li><strong>Perform Unit, End-to-End, and Integration testing:</strong> Writing unit, end-to-end, and integration tests is paramount to testing the functionality of the application builds.</li>
</ol>
<p>Then, you'd want to establish a solid <strong>Continuous Deployment</strong> <strong>workflow</strong> with the following steps:</p>
<ol>
<li><strong>Separation of environments:</strong> Separate dev, staging, and production environments for environment-specific testing.</li>
<li><strong>Rollout method selection:</strong> Select rollout strategies depending on your needs, such as Rolling Updates, A/B Testing, Canary Deployments, and Feature Flagging.</li>
</ol>
<p>Next, you should implement a robust <strong>monitoring</strong> mechanism for applications by leveraging monitoring systems such as Prometheus for monitoring, Grafana for visualization, and Grafana On Call for incident/on-call management tool.</p>
<p>And finally, after creating the above mechanism, the last step would be to use the provided <strong>RBAC</strong> systems in place. You'd start from cloud platforms and move on to DevOps tools being used implement the concept of least privilege on all levels and add them as a part of DevOps compliance practices.</p>
<h2 id="heading-wrapping-up">Wrapping up</h2>
<p>In this article, we discussed the importance of RBAC in the world of DevOps and how teams can leverage it in the industry to secure production environments. </p>
<p>We also discussed what feature flagging is, its importance for feature releases, and how it leverages RBAC to manage user permissions. </p>
<p>For a better understanding, we discussed a use case in which we saw how implementing Flagsmith could have saved a downtime incident, and how a DevOps compliance process could give strength to feature releases in production.  </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Implement Infrastructure as Code with AWS ]]>
                </title>
                <description>
                    <![CDATA[ Infrastructure as code is the process of provisioning and managing your cloud resources by writing a template file that is both human-readable and machine consumable.  For AWS cloud development, the built-in choice for infrastructure as code is AWS C... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-implement-infrastructure-as-code-with-aws/</link>
                <guid isPermaLink="false">66b9ef60d5fabb18363d1946</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Infrastructure as code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kayode Adeniyi ]]>
                </dc:creator>
                <pubDate>Mon, 31 Oct 2022 17:07:04 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/network-g381392bcb_1280.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Infrastructure as code is the process of provisioning and managing your cloud resources by writing a template file that is both human-readable and machine consumable. </p>
<p>For AWS cloud development, the built-in choice for infrastructure as code is AWS CloudFormation.</p>
<p>Using IaC, developers can manage a project’s infrastructure efficiently, allowing them to easily configure and maintain changes within a project’s architecture and resources.</p>
<p>There are numerous IaC tools available such as Ansible, Puppet, Chef, and Terraform. </p>
<p>But for this guide, we will use CloudFormation, which was made specifically for AWS resources.</p>
<h2 id="heading-what-you-will-learn-in-this-tutorial">What You Will Learn in This Tutorial</h2>
<p>After going through this tutorial, you will understand how to maintain your resources within one software file. </p>
<p>In addition to this, you will learn the benefits related to speed that Infrastructure as Code brings to the table. Without IaC, the time and cost of manual deployment of various infrastructures can be much greater compared to maintaining infrastructure as software. </p>
<p>In this article, we will consider an example. It will demonstrate manually provisioning resources vs deploying a CloudFormation script to create a serverless Lambda function and REST API on AWS.</p>
<h3 id="heading-services-well-use-in-this-tutorial">Services We'll Use in This Tutorial</h3>
<p>We will use the following services to implement Infrastructure as Code in AWS: </p>
<table><colgroup><col><col></colgroup><tbody><tr><td><p><span>AWS Service Name</span></p></td><td><p><span>Description</span></p></td></tr><tr><td><p><span>AWS API Gateway (API GW)</span></p></td><td><p><span>We will use this service to create our REST API. It also allows for creating, publishing, and monitoring secure Socket and Restful APIs.</span></p></td></tr><tr><td><p><span>AWS Lambda</span></p></td><td><p><span>We will use this service to set up an example serverless function on the backend which will be integrated with our REST API.</span></p></td></tr><tr><td><p><span>Identity Access and Management (IAM)</span></p></td><td><p><span>Service that allows you to manage access to various AWS services through roles and permissions. We will create a role for our Lambda function so that we can access the API gateway.</span></p></td></tr><tr><td><p><span>AWS CLI</span></p></td><td><p><span>To work with AWS services and resources, you can use the command line interface rather than the console for easy access.</span></p></td></tr><tr><td><p><span>AWS SAM</span></p></td><td><p><span>An abstraction of CoudFormation allows developing the serverless applications.</span></p></td></tr></tbody></table>

<p>For those who are new to AWS, it's good to have some knowledge of it to understand the article. So, you can follow along with me by creating an account on AWS <a target="_blank" href="https://aws.amazon.com/console/">here</a> and making sure you have <a target="_blank" href="https://aws.amazon.com/cli/">AWS CLI</a> installed to work with the example.</p>
<h3 id="heading-overview-of-the-example">Overview of the Example</h3>
<p>For the article, we will be implementing a REST API with an API gateway. It will be integrated with a serverless backend Lambda function that handles POST and gets requests made by our API.</p>
<p>The first step will show you how to manually build and deploy these resources using the AWS console. The second step will show you how to automate the process using CloudFormation.</p>
<h2 id="heading-how-to-deploy-manually">How to Deploy Manually</h2>
<p>In manual deployment, we will work inside the AWS console. It is a bit hard to track changes while working outside the local IDE, especially for large-scale projects. </p>
<p>In the first step, we will create a Lambda function.</p>
<p><img src="https://lh5.googleusercontent.com/dA4vn3WDgKdVRCf9dJyZjGG5CxtHGVrB-EuGs3EW9P0KkIGxMf64fWg-NXNhFGaVPios3ryNb4OpUfNCMEYvWE1rOtk1QfE_FjSF01E4DVUUlouuUY4KdzCt8J68_OnTz72x6PmousW5auYLYMZF_lYP69T-VljKBwD39ssmU2R-463xL7UQQCM9kg" alt="Image" width="1600" height="724" loading="lazy"></p>
<p>If you want your Lambda function to work with some other service like Comprehend, you must give permissions for that service. So, make sure to create a role with these permissions.</p>
<p>Following is our Lambda function that will return “Hello World” when integrated with the API gateway. </p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> json

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>
    <span class="hljs-comment"># TODO implement</span>
    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">'statusCode'</span>: <span class="hljs-number">200</span>,
        <span class="hljs-string">'body'</span>: json.dumps(<span class="hljs-string">'Hello World!'</span>)
    }
</code></pre>
<p>Now that we have configured our Lambda function, the next step is to create a REST API to interact with the Lambda function. </p>
<p>For this, go to Amazon API Gateway, Click create API, and select REST API from the provided options.</p>
<p><img src="https://lh4.googleusercontent.com/DZDV8mRaosjWYOyeQgPpI2jI8U73bAYAJ-Y_FIEVZMYD_KjjSatXTNcUiv9rgpoBUg-tOL7Kc4-nXthNR8MsUcW8NtrbD7Sg6fx8VQHHG98DqBZDGvAC2alCjHunqu1W9OynLD83NcVu-kKE1jq4nu5byTcq6cLxjmeaAdI05l0MTfi37sxcIRcfSQ" alt="Image" width="1600" height="677" loading="lazy"></p>
<p>Now we will integrate Lambda with the API. For this, create a GET method from the actions menu and point our REST API to the Lambda function.</p>
<p><img src="https://lh4.googleusercontent.com/H8Aw6L3o8xpkEPJQI2X0Hw7O2hAmyYuUKeEY2Q8SH0DOR7R_uCAJc94Z4lnJCsT-ZIYkrky3GWqroyrhSgUr2Hr8kiN8Ye3jOyTJdO_3WZSqTdC9shRDOju9oNIHx_ijkj2B3ig7xf83l2emLGVZei7Obj9twWhQifWMnR256HAFdUrc26fq52-70Q" alt="Image" width="1600" height="692" loading="lazy"></p>
<p>We are in a position to deploy and test our API for its proper integration with Lambda. Select any stage name you want – for this example, I'm using “prod”.</p>
<p><img src="https://lh6.googleusercontent.com/YYKoUxe7L76Mcy6dJSK8rGo5b2KL3tru7D4pwGDqdREoHuPxNICkjGYvVT6KVDe_TrRDsfFj3wfu9TysVLDaJ9kb-fTyQoyc2DAYQ9y42Wtf1S4TGVAAmvdkQvgTVtxfwkU97_XRIAt4ge5HaDtnoroKS_uMPanS2GhC9Tk2mNhgyr1DAp5r9WG8tA" alt="Image" width="1600" height="1005" loading="lazy"></p>
<p>After deploying the API, you can see a URL on the “prod” stage. Hitting this URL will trigger the Lambda function. As we have returned “Hello World” from our Lambda function, so you should be able to see the desired result.</p>
<p><img src="https://lh6.googleusercontent.com/TY4GfBhk2V2RARNKYvD894FxeFKOZd4csJvj-aori2Ct524F1jOpx43CQpWEP-2irtjJTGIXgf6fhI4JZej_DgjEFM0UL0mzPoe7L2BQBHrMY5mv8mMbW6MbPKE-Qv7CC95VUPjqKeJ43L7iUea2qj4HMixEhm3p79Dma3cNxt4PanqJ49Hi6YJgrA" alt="Image" width="1600" height="415" loading="lazy"></p>
<h2 id="heading-how-to-deploy-with-cloudformation">How to Deploy with CloudFormation</h2>
<p>Up to this point, we have seen how manual deployment works, which usually takes a few minutes. </p>
<p>But let’s imagine that we have more than one API, method, and more than one developer working on them. In this scenario, tracking all the resources and changes would be challenging. </p>
<p>So, in this section, we will use AWS CloudFormation instead. It will give flexibility to the developers, allowing them to adjust their Infrastructure with a simple script.</p>
<h3 id="heading-how-does-cloudformation-work">How Does CloudFormation Work?</h3>
<p>We will use the YAML file to provision and declare these resources and deploy them to AWS to create a CloudFormation stack. CloudFormation is a stack that contains all the resources required for the project. </p>
<p>We will be using the SAM template as described above in the services section. It is an abstraction of CloudFormation to build serverless applications with less YAML code. </p>
<p>For those who don’t know about YAML, you can think about it like JSON. But CloudFormation uses both of these file formats.</p>
<p><strong>In the first step,</strong> we head to our local IDE and write the same Lambda function as we did in the AWS console.</p>
<p><strong>helloworld.py</strong>:</p>
<pre><code class="lang-py"><span class="hljs-keyword">import</span> json

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">lambda_handler</span>(<span class="hljs-params">event, context</span>):</span>
    <span class="hljs-comment"># TODO implement</span>
    <span class="hljs-keyword">return</span> {
        <span class="hljs-string">'statusCode'</span>: <span class="hljs-number">200</span>,
        <span class="hljs-string">'body'</span>: json.dumps(<span class="hljs-string">'Hello World!'</span>)
    }
</code></pre>
<p>Next, we will create a <strong>template</strong>.yaml file containing our infrastructure. We will define our Lambda function and API Gateway in this file. </p>
<p>To build this file, we need to add some information that is common to all SAM templates.</p>
<p><strong>template.yaml</strong>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">AWSTemplateFormatVersion:</span> <span class="hljs-string">'2010-09-09'</span>
<span class="hljs-attr">Transform:</span> <span class="hljs-string">AWS::Serverless-2016-10-31</span>
<span class="hljs-attr">Description:</span> <span class="hljs-string">First</span> <span class="hljs-string">CloudFormation</span> <span class="hljs-string">template</span>
</code></pre>
<p>Now, we have to add “Globals” to this CloudFormation template.yaml file. <strong>Globals</strong> are the common configs for the resources that you are going to deploy. Globals allow you to declare information globally for a specific resource type rather than specifying it again and again for different resources. </p>
<p><strong>template.yaml</strong>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">Globals:</span>
    <span class="hljs-comment">#Common to all Lambda functions you create</span>
    <span class="hljs-attr">Function:</span>
      <span class="hljs-attr">MemorySize:</span> <span class="hljs-number">128</span>
      <span class="hljs-attr">Runtime:</span> <span class="hljs-string">python3.6</span>
      <span class="hljs-attr">Timeout:</span> <span class="hljs-number">5</span>
</code></pre>
<p>We define have to define the Resources tag in our template.yaml file. The Lambda function and REST API will come under this tag. </p>
<p><strong>template.yaml</strong>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">Resources:</span>

    <span class="hljs-comment">##Lambda and API GW Integrated</span>
    <span class="hljs-attr">helloworld:</span>
        <span class="hljs-attr">Type:</span> <span class="hljs-string">AWS::Serverless::Function</span>
        <span class="hljs-attr">Properties:</span>
          <span class="hljs-comment">#filename.functionname</span>
          <span class="hljs-attr">Handler:</span> <span class="hljs-string">helloworld.lambda_handler</span>

          <span class="hljs-comment">#REST API created</span>
          <span class="hljs-attr">Events:</span>
            <span class="hljs-attr">PostAdd:</span>
              <span class="hljs-attr">Type:</span> <span class="hljs-string">Api</span>
              <span class="hljs-attr">Properties:</span>
                <span class="hljs-attr">Path:</span> <span class="hljs-string">/helloworld</span>
                <span class="hljs-attr">Method:</span> <span class="hljs-string">get</span>
</code></pre>
<p>In the above code, we define parameters for creating the Lambda function. For the event, we create a REST API that triggers the Lambda function. </p>
<p><strong>Note:</strong> There is an array of parameters like CodeURI and description that you can specify for your serverless function. The best way to create a template file is to go through the CloudFormation docs and see the parameters available for your specified resource/service.</p>
<h2 id="heading-how-to-deploy-the-template-file">How to Deploy the Template File</h2>
<p>We can deploy our <strong>template</strong>.yaml file using the following two AWS CLI commands:</p>
<pre><code class="lang-yaml"><span class="hljs-comment">##s3 bucket stores our sam template which we need to deploy</span>
<span class="hljs-string">aws</span> <span class="hljs-string">cloudformation</span> <span class="hljs-string">package</span> <span class="hljs-string">--template-file</span> <span class="hljs-string">template.yaml</span> <span class="hljs-string">--output-template-file</span> <span class="hljs-string">sam-template.yaml</span> <span class="hljs-string">--s3-bucket</span> <span class="hljs-string">helloworld-sam</span>
</code></pre>
<p>After running the above command, you will be able to see a SAM template file. We will use this file in the second command below. </p>
<p>In this command, give your appropriate path to the sam-template.yaml file:</p>
<pre><code class="lang-yaml"><span class="hljs-comment">#Deploy stack</span>
<span class="hljs-comment">#point to template file created by a previous command and a stack name as well as your region you're deploying</span>

<span class="hljs-string">aws</span> <span class="hljs-string">cloudformation</span> <span class="hljs-string">deploy</span> <span class="hljs-string">--template-file</span> <span class="hljs-string">/path</span> <span class="hljs-string">to</span> <span class="hljs-string">sam-template.yaml</span> <span class="hljs-string">file</span> <span class="hljs-string">--stack-name</span> <span class="hljs-string">test-stack</span> <span class="hljs-string">--capabilities</span> <span class="hljs-string">CAPABILITY_IAM</span> <span class="hljs-string">--region</span> <span class="hljs-string">us-east-1</span>
</code></pre>
<p>After executing both of these commands, you will see the stack created in the CLI. You can verify it using CloudFormation in the console. </p>
<p>Here you will see all the resources provisioned through the code created and deployed using the template.yaml file. </p>
<p><img src="https://lh5.googleusercontent.com/h9wcmfT3Kx-jSIMEeCqZv-0qFTs05puZ6ox5CuRBywubpqdiPRpnYiCZZTaYFBaSDEuQmi5HtXCPNPpZcuKCs_jtBTc6WZP5pUceHxR-jRWmRLycxFwESMYkdYpN5Qi5c3_TACNRjpqfwpRdDf5qV6Wee5-uAMhtvVoAWUtJvIA4h4no_fk-NPT7Sw" alt="Image" width="1600" height="1168" loading="lazy"></p>
<p>You can click on API and access the URL to check the output as we did for the manual deployment. </p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>That’s it – you have successfully implemented infrastructure as code in AWS using CloudFormation.</p>
<p>I hope this article has been helpful for anyone wanting to understand implementing infrastructure as code in AWS.</p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/kadeniyi/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/mkbadeniyi">Twitter</a></p>
<p>Hasta la vista!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Architect a Blockchain on Kubernetes – K8S Microservice Tutorial ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I will describe how to use microservices architecture and Kubernetes to build a blockchain.  The technologies usually used for blockchains are purpose-driven, and you can use them for other projects as well. The examples in this arti... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-architect-a-blockchain-on-kubernetes-k8s-microservice-tutorial/</link>
                <guid isPermaLink="false">66b9ef5d148b506e83d90ab8</guid>
                
                    <category>
                        <![CDATA[ Blockchain ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Kubernetes ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kayode Adeniyi ]]>
                </dc:creator>
                <pubDate>Mon, 17 Oct 2022 16:02:43 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/10/Screenshot-2022-10-01-at-07.39.09.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I will describe how to use microservices architecture and Kubernetes to build a blockchain. </p>
<p>The technologies usually used for blockchains are purpose-driven, and you can use them for other projects as well.</p>
<p>The examples in this article can readily handle heavy loads and remain responsive and quick to execute user requests. </p>
<p>Because the cryptocurrency industry is growing fast, a lot of countries are setting rules around how everything should be managed. As a result, I will adhere to certain regulations and take into account certain details, such as the characteristics of the blockchain technology.</p>
<p>For instance, you can have overloads and performance problems with blockchain technology. And as the market for cryptocurrencies and blockchain technology expands, new products are more likely to appeal to a wide range of active blockchain technology users. </p>
<p>Because of this, I had to find a way to prevent the program from becoming overloaded in the event of a significant increase in users.</p>
<h1 id="heading-tutorial-prerequisites">Tutorial Prerequisites</h1>
<p>For this walkthrough, these are the following technologies we will be using. You should be familiar with them:</p>
<ul>
<li><strong>Node.js</strong> (specifically, the NestJS framework) for backend development. Nest.js forces you to use a modular structure where each feature can be isolated and easily connected/disconnected to/from other modules. Nest supports TypeScript out-of-the-box.</li>
<li><strong>PostgreSQL</strong> is the database we'll use to collect data.</li>
<li><strong>Kafka JS</strong> serves incoming loads and establishes communication between microservices.</li>
<li><strong>Helm charts and Kubernetes (k8s)</strong> for deployment. These tools will enable easy deployment of scalable microservices infrastructure on any cloud platform (we will use AWS EKS)</li>
</ul>
<p>Also, this article assumes you have a decent level of knowledge about Kubernetes, Helm, and Node. Let's dive in.</p>
<h1 id="heading-development-method">Development Method</h1>
<p>Our primary goal for the first phase is to divide our application into microservices.</p>
<p>In addition to helping with service communication, load balancing with Kafka enables the one-by-one processing of input data. When we have many customers, processing times may increase, but at least the service will continue and be preserved.</p>
<p>Additionally, if the cluster has enough resources, we can spawn extra consumers for the group that manages particular events. This reduces delays and accelerates task processing.</p>
<p>In this situation, we will develop six different microservices:</p>
<ol>
<li><strong>Admin Microservice</strong> – We'll use the admin microservice for all administrative panel logic, which should be isolated from user-facing functionality.</li>
<li><strong>Core Microservice</strong> – Logic pertaining to users and their accounts is contained in the core microservice. Identification, gifts, charts, profiles, and so on. However, this microservice does not carry out the duties of a financial service, such as processing payments and exchanging currency.</li>
<li><strong>Payment Microservice</strong> – A financial service called a "payment microservice" includes logic for trade, exchange, and withdrawal transactions. There will be integrations with CEX and DeFi solutions.</li>
<li><strong>Email and notification service</strong> – This microservice is in charge of informing the user of emails, push notifications, and other types of alerts. It contains a separate Kafka queue for requests from other microservices to send users emails or notifications.</li>
<li><strong>Cron Tasks</strong> – A microservice called Cron Tasks Service transmits predetermined events for task processing. Microservices don't carry out tasks on their own. Holding such a microservice helps prevent skipping cron job iterations when, for instance, the processing service is down due to deployment or a breakdown. The event will remain in a queue as it waits to be executed.</li>
<li><strong>Webhooks Microservice</strong> – The goal of the webhooks microservice is to prevent any events from external APIs that may be very significant and contain transaction statuses or other vital data from being missed. Such events are processed after being queued up (based on the sender API).</li>
</ol>
<p>Now let's see how to make these microservices using Nest.js.</p>
<p>For the Kafka messages broker, you'll need to create configuration options. In order to store the shared modules and configurations of all microservices, we will establish a shared resources folder.</p>
<h2 id="heading-microservices-configuration-options">Microservices Configuration Options</h2>
<p>Production apps must have configuration. The configuration is crucial for understanding what your production application consumes as you build out a microservice application. It is usually recommended practice to keep configuration settings distinct from your code when developing microservices.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { ClientProviderOptions, Transport } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/microservices'</span>;

<span class="hljs-keyword">import</span> CONFIG <span class="hljs-keyword">from</span> <span class="hljs-string">'@application-config'</span>;

<span class="hljs-keyword">import</span> { ConsumerGroups, ProjectMicroservices } <span class="hljs-keyword">from</span> <span class="hljs-string">'./microservices.enum'</span>;

<span class="hljs-keyword">const</span> { BROKER_HOST, BROKER_PORT } = CONFIG.KAFKA;




<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> PRODUCER_CONFIG = (name: ProjectMicroservices): <span class="hljs-function"><span class="hljs-params">ClientProviderOptions</span> =&gt;</span> ({

 name,

 <span class="hljs-attr">transport</span>: Transport.KAFKA,

 <span class="hljs-attr">options</span>: {

   <span class="hljs-attr">client</span>: {

     <span class="hljs-attr">brokers</span>: [${BROKER_HOST}:${BROKER_PORT}],

   },

 }

});



<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> CONSUMER_CONFIG = <span class="hljs-function">(<span class="hljs-params">groupId: ConsumerGroups</span>) =&gt;</span> ({

 <span class="hljs-attr">transport</span>: Transport.KAFKA,

 <span class="hljs-attr">options</span>: {

   <span class="hljs-attr">client</span>: {

     <span class="hljs-attr">brokers</span>: [${BROKER_HOST}:${BROKER_PORT}],

   },

   <span class="hljs-attr">consumer</span>: {

     groupId

   }

 }

});
</code></pre>
<p>Let's link our microservice for the admin panel to Kafka in consumer mode. We can detect and manage events from topics thanks to it.</p>
<p>Make the app operate in microservice mode so that events can be consumed like this:</p>
<pre><code class="lang-js">app.connectMicroservice(CONSUMER_CONFIG(ConsumerGroups.ADMIN));

 <span class="hljs-keyword">await</span> app.startAllMicroservices();
</code></pre>
<p>We can see that groupId is included in the consumer configuration. It's a crucial choice that will enable customers from the same group to get events from topics and share them with one another to process them more quickly.</p>
<p>For instance, we can use autoscaling to launch more pods to divide loading between them and speed up the process double if our microservice receives events more quickly than it can process them.</p>
<p>Consumers must be included in the group for this to work, and after scaling, spawned pods will also be included. They won't have to handle the same subject events from several Kafka partitions because they can share loading.</p>
<p>Let's look at an illustration of how we can use Nest to capture and handle Kafka events.</p>
<h2 id="heading-consumer-controller">Consumer Controller</h2>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Controller } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-keyword">import</span> { Ctx, KafkaContext, MessagePattern, EventPattern, Payload } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/microservices'</span>;




@Controller(<span class="hljs-string">'consumer'</span>)

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConsumerController</span> </span>{

 @MessagePattern(<span class="hljs-string">'hero'</span>)

 readMessage(@Payload() message: any, @Ctx() context: KafkaContext) {

   <span class="hljs-keyword">return</span> message;

 }




 @EventPattern(<span class="hljs-string">'event-hero'</span>)

 sendNotif(data) {

   <span class="hljs-built_in">console</span>.log(data);

 }

}
</code></pre>
<p>Customers can operate in two modes. It accepts events, processes them without delivering a response (EventPattern decorator), or, after processing an event, returns the response to the producer (MessagePattern decorator). </p>
<p>Since it doesn't contain any additional source code layers to enable request/response functionality, EventPattern is preferable and you should choose it wherever possible.</p>
<h2 id="heading-who-are-the-producers">Who Are the Producers?</h2>
<p>We must supply producer configuration for a module that will be in charge of transmitting events in order to link producers.</p>
<h3 id="heading-producer-connection">Producer Connection</h3>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Module } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-keyword">import</span> DatabaseModule <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/database/database.module'</span>;

<span class="hljs-keyword">import</span> { ClientsModule } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/microservices'</span>;

<span class="hljs-keyword">import</span> { ProducerController } <span class="hljs-keyword">from</span> <span class="hljs-string">'./producer.controller'</span>;

<span class="hljs-keyword">import</span> { PRODUCER_CONFIG } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/microservices/microservices.config'</span>;

<span class="hljs-keyword">import</span> { ProjectMicroservices } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/microservices/microservices.enum'</span>;




@Module({

 <span class="hljs-attr">imports</span>: [

   DatabaseModule,

   ClientsModule.register([PRODUCER_CONFIG(ProjectMicroservices.ADMIN)]),

 ],

 <span class="hljs-attr">controllers</span>: [ProducerController],

 <span class="hljs-attr">providers</span>: [],

})

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerModule</span> </span>{}
</code></pre>
<h3 id="heading-event-based-producer">Event-based producer</h3>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Controller, Get, Inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-keyword">import</span> { ClientKafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/microservices'</span>;

<span class="hljs-keyword">import</span> { ProjectMicroservices } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/microservices/microservices.enum'</span>;




@Controller(<span class="hljs-string">'producer'</span>)

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerController</span> </span>{

 <span class="hljs-keyword">constructor</span>(

   @Inject(ProjectMicroservices.ADMIN)

   private readonly client: ClientKafka,

 ) {}




 @Get()

 <span class="hljs-keyword">async</span> getHello() {

   <span class="hljs-built_in">this</span>.client.emit(<span class="hljs-string">'event-hero'</span>, { <span class="hljs-attr">msg</span>: <span class="hljs-string">'Event Based'</span>});

 }

}
</code></pre>
<h3 id="heading-requestresponse-based-producer">Request/response-based producer</h3>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Controller, Get, Inject } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/common'</span>;

<span class="hljs-keyword">import</span> { ClientKafka } <span class="hljs-keyword">from</span> <span class="hljs-string">'@nestjs/microservices'</span>;

<span class="hljs-keyword">import</span> { ProjectMicroservices } <span class="hljs-keyword">from</span> <span class="hljs-string">'@shared/microservices/microservices.enum'</span>;




@Controller(<span class="hljs-string">'producer'</span>)

<span class="hljs-keyword">export</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProducerController</span> </span>{

 <span class="hljs-keyword">constructor</span>(

   @Inject(ProjectMicroservices.ADMIN)

   private readonly client: ClientKafka,

 ) {}




 <span class="hljs-keyword">async</span> onModuleInit() {

   <span class="hljs-comment">// Need to subscribe to a topic</span>

   <span class="hljs-comment">// to make the response receiving from Kafka microservice possible</span>

   <span class="hljs-built_in">this</span>.client.subscribeToResponseOf(<span class="hljs-string">'hero'</span>);

   <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.client.connect();

 }




 @Get()

 <span class="hljs-keyword">async</span> getHello() {

   <span class="hljs-keyword">const</span> responseBased = <span class="hljs-built_in">this</span>.client.send(<span class="hljs-string">'hero'</span>, { <span class="hljs-attr">msg</span>: <span class="hljs-string">'Response Based'</span> });

      <span class="hljs-keyword">return</span> responseBased;

 }

}
</code></pre>
<p>Each microservice has the option of operating in one of the two modes—producer or consumer—or in both modes simultaneously (mixed). </p>
<p>Microservices typically employ mixed mode for load balancing, producing events to the subject, and consuming them while equally splitting the load.</p>
<p>For each microservice, we'll use a Kubernetes setup based on Helm chart templates.</p>
<p><img src="https://lh5.googleusercontent.com/t7eB19l8xOFm4Fsm-cJ1HMAkBhIOBiHHs-psH_6NXPIqbOPFWI1uMlbOYeD0mCaD3BLNjR070IktMx1V-cTfThBZ3GzgKo2aNnLtObBJvzq09YZNhL5nuOOY9FUE2HBx_FF0L3VqCuFZBSWV6532GmXu7OFUiOtAjTufDfJEEhI-wPtfn-EazwRCIA" alt="Image" width="498" height="700" loading="lazy"></p>
<p>There are several configuration files in the template:</p>
<ul>
<li>Hpa (horizontal pod autoscaler)</li>
<li>Ingress controller</li>
<li>Service</li>
<li>Deployment</li>
</ul>
<p>We'll examine each configuration file separately (without Helm templating).</p>
<h3 id="heading-how-to-deploy-the-admin-api">How to deploy the admin-API</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api</span>

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>

 <span class="hljs-attr">selector:</span>

   <span class="hljs-attr">matchLabels:</span>

     <span class="hljs-attr">app:</span> <span class="hljs-string">admin-api</span>

 <span class="hljs-attr">template:</span>

   <span class="hljs-attr">metadata:</span>

     <span class="hljs-attr">labels:</span>

       <span class="hljs-attr">app:</span> <span class="hljs-string">admin-api</span>

   <span class="hljs-attr">spec:</span>

     <span class="hljs-attr">containers:</span>

     <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api</span>

       <span class="hljs-attr">Image:</span> <span class="hljs-string">xxx208926xxx.dkr.ecr.us-east-1.amazonaws.com/project-name/stage/admin-api</span>

       <span class="hljs-attr">resources:</span>

         <span class="hljs-attr">requests:</span>

           <span class="hljs-attr">cpu:</span> <span class="hljs-string">250m</span>

           <span class="hljs-attr">memory:</span> <span class="hljs-string">512Mi</span>

         <span class="hljs-attr">limits:</span>

           <span class="hljs-attr">cpu:</span> <span class="hljs-string">250m</span>

           <span class="hljs-attr">memory:</span> <span class="hljs-string">512Mi</span>

       <span class="hljs-attr">ports:</span>

         <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">80</span>

       <span class="hljs-attr">env:</span>

         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">NODE_ENV</span>

           <span class="hljs-attr">value:</span> <span class="hljs-string">production</span>




         <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">APP_PORT</span>

           <span class="hljs-attr">value:</span> <span class="hljs-string">"80"</span>
</code></pre>
<p>You can include more minimal configurations, such as resource limitations, health check configurations, update strategies, and so on in a deployment. </p>
<h3 id="heading-admin-api-service">Admin-API service</h3>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>

<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api</span>

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">selector:</span>

   <span class="hljs-attr">app:</span> <span class="hljs-string">admin-api</span>

 <span class="hljs-attr">ports:</span>

   <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api-port</span>

     <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>

     <span class="hljs-attr">targetPort:</span> <span class="hljs-number">80</span>

     <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>

 <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span>
</code></pre>
<p>To use this service, we must make it available to the public. Let's utilise SSL setup to leverage a secure HTTPS connection and expose our app via a load balancer.</p>
<p>On our cluster, we must deploy a load balancer controller. The most widely used answer is as follows: Load Balancer Controller for AWS.</p>
<p>Next, we must set up ingress with the following settings:</p>
<h3 id="heading-admin-api-ingress-controller">Admin-API ingress controller</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.k8s.io/v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Ingress</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">namespace:</span> <span class="hljs-string">default</span>

 <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api-ingress</span>

 <span class="hljs-attr">annotations:</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/load-balancer-name:</span> <span class="hljs-string">admin-api-alb</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/ip-address-type:</span> <span class="hljs-string">ipv4</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/tags:</span> <span class="hljs-string">Environment=production,Kind=application</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/scheme:</span> <span class="hljs-string">internet-facing</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/certificate-arn:</span> <span class="hljs-string">arn:aws:acm:us-east-2:xxxxxxxx:certificate/xxxxxxxxxx</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/listen-ports:</span> <span class="hljs-string">'[{"HTTP": 80}, {"HTTPS":443}]'</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-protocol:</span> <span class="hljs-string">HTTPS</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-path:</span> <span class="hljs-string">/healthcheck</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-interval-seconds:</span> <span class="hljs-string">'15'</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/ssl-redirect:</span> <span class="hljs-string">'443'</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/group.name:</span> <span class="hljs-string">admin-api</span>

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">ingressClassName:</span> <span class="hljs-string">alb</span>

 <span class="hljs-attr">rules:</span>

   <span class="hljs-bullet">-</span> <span class="hljs-attr">host:</span> <span class="hljs-string">example.com</span>

     <span class="hljs-attr">http:</span>

       <span class="hljs-attr">paths:</span>

         <span class="hljs-bullet">-</span> <span class="hljs-attr">path:</span> <span class="hljs-string">/*</span>

           <span class="hljs-attr">pathType:</span> <span class="hljs-string">ImplementationSpecific</span>

           <span class="hljs-attr">backend:</span>

             <span class="hljs-attr">service:</span>

               <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api</span>

               <span class="hljs-attr">port:</span>

                 <span class="hljs-attr">number:</span> <span class="hljs-number">80</span>
</code></pre>
<p>Once this configuration has been applied, a new alb load balancer will be formed. We must construct a domain with the name we specified in the 'host' option and direct traffic to our load balancer from this host.</p>
<h3 id="heading-admin-api-autoscaling-configuration">Admin-API autoscaling configuration</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">autoscaling/v2beta1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">HorizontalPodAutoscaler</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api-hpa</span>

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">scaleTargetRef:</span>

   <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>

   <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>

   <span class="hljs-attr">name:</span> <span class="hljs-string">admin-api</span>

 <span class="hljs-attr">minReplicas:</span> <span class="hljs-number">1</span>

 <span class="hljs-attr">maxReplicas:</span> <span class="hljs-number">2</span>

 <span class="hljs-attr">metrics:</span>

   <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">Resource</span>

     <span class="hljs-attr">resource:</span>

       <span class="hljs-attr">name:</span> <span class="hljs-string">cpu</span>

       <span class="hljs-attr">targetAverageUtilization:</span> <span class="hljs-number">90</span>
</code></pre>
<h2 id="heading-how-does-helm-come-into-the-picture">How Does Helm Come into the Picture?</h2>
<p>When we want to make our k8s infrastructure less complex, Helm is quite helpful. Without this tool, running it on a cluster requires writing numerous YML files.</p>
<p>Additionally, we must consider the relationships among applications, labels, names, and so on. Helm, on the other hand, can simplify things. It functions similarly to a package manager, allowing us to make an app template, prepare it using short commands, and then launch it.</p>
<p>Let's create our templates using Helm.</p>
<h3 id="heading-admin-api-deployment-helm-chart">Admin-API deployment (Helm chart)</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> {{ <span class="hljs-string">.Values.appName</span> }}

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">replicas:</span> {{ <span class="hljs-string">.Values.replicas</span> }}

 <span class="hljs-attr">selector:</span>

   <span class="hljs-attr">matchLabels:</span>

     <span class="hljs-attr">app:</span> {{ <span class="hljs-string">.Values.appName</span> }}

 <span class="hljs-attr">template:</span>

   <span class="hljs-attr">metadata:</span>

     <span class="hljs-attr">labels:</span>

       <span class="hljs-attr">app:</span> {{ <span class="hljs-string">.Values.appName</span> }}

   <span class="hljs-attr">spec:</span>

     <span class="hljs-attr">containers:</span>

     <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> {{ <span class="hljs-string">.Values.appName</span> }}

       <span class="hljs-attr">image:</span> {{ <span class="hljs-string">.Values.image.repository</span> }}<span class="hljs-string">:{{</span> <span class="hljs-string">.Values.image.tag</span> <span class="hljs-string">}}"</span>

       <span class="hljs-attr">imagePullPolicy:</span> {{ <span class="hljs-string">.Values.image.pullPolicy</span> }}

       <span class="hljs-attr">ports:</span>

       <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> {{ <span class="hljs-string">.Values.internalPort</span> }}

       {{<span class="hljs-bullet">-</span> <span class="hljs-string">with</span> <span class="hljs-string">.Values.env</span> }}

       <span class="hljs-attr">env:</span> {{ <span class="hljs-string">tpl</span> <span class="hljs-string">(.</span> <span class="hljs-string">|</span> <span class="hljs-string">toYaml)</span> <span class="hljs-string">$</span> <span class="hljs-string">|</span> <span class="hljs-string">nindent</span> <span class="hljs-number">12</span> }}

       {{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}
</code></pre>
<h3 id="heading-admin-api-service-helm-chart">Admin-API service (Helm chart)</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> {{ <span class="hljs-string">.Values.global.appName</span> }}

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">selector:</span>

   <span class="hljs-attr">app:</span> {{ <span class="hljs-string">.Values.global.appName</span> }}

 <span class="hljs-attr">ports:</span>

   <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> {{ <span class="hljs-string">.Values.global.appName</span> }}<span class="hljs-string">-port</span>

     <span class="hljs-attr">port:</span> {{ <span class="hljs-string">.Values.externalPort</span> }}

     <span class="hljs-attr">targetPort:</span> {{ <span class="hljs-string">.Values.internalPort</span> }}

     <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>

 <span class="hljs-attr">type:</span> <span class="hljs-string">NodePort</span>
</code></pre>
<h3 id="heading-admin-api-ingress-helm-chart">Admin-API ingress (Helm chart)</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.k8s.io/v1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">Ingress</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">namespace:</span> <span class="hljs-string">default</span>

 <span class="hljs-attr">name:</span> <span class="hljs-string">ingress</span>

 <span class="hljs-attr">annotations:</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/load-balancer-name:</span> {{ <span class="hljs-string">.Values.ingress.loadBalancerName</span> }}

   <span class="hljs-attr">alb.ingress.kubernetes.io/ip-address-type:</span> <span class="hljs-string">ipv4</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/tags:</span> {{ <span class="hljs-string">.Values.ingress.tags</span> }}

   <span class="hljs-attr">alb.ingress.kubernetes.io/scheme:</span> <span class="hljs-string">internet-facing</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/certificate-arn:</span> {{ <span class="hljs-string">.Values.ingress.certificateArn</span> }}

   <span class="hljs-attr">alb.ingress.kubernetes.io/listen-ports:</span> <span class="hljs-string">'[{"HTTP": 80}, {"HTTPS":443}]'</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-protocol:</span> <span class="hljs-string">HTTPS</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-path:</span> {{ <span class="hljs-string">.Values.ingress.healthcheckPath</span> }}

   <span class="hljs-attr">alb.ingress.kubernetes.io/healthcheck-interval-seconds:</span> {{ <span class="hljs-string">.Values.ingress.healthcheckIntervalSeconds</span> }}

   <span class="hljs-attr">alb.ingress.kubernetes.io/ssl-redirect:</span> <span class="hljs-string">'443'</span>

   <span class="hljs-attr">alb.ingress.kubernetes.io/group.name:</span> {{ <span class="hljs-string">.Values.ingress.loadBalancerGroup</span> }}

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">ingressClassName:</span> <span class="hljs-string">alb</span>

 <span class="hljs-attr">rules:</span>

   <span class="hljs-bullet">-</span> <span class="hljs-attr">host:</span> {{ <span class="hljs-string">.Values.adminApi.domain</span> }}

     <span class="hljs-attr">http:</span>

       <span class="hljs-attr">paths:</span>

         <span class="hljs-bullet">-</span> <span class="hljs-attr">path:</span> {{ <span class="hljs-string">.Values.adminApi.path</span> }}

           <span class="hljs-attr">pathType:</span> <span class="hljs-string">ImplementationSpecific</span>

           <span class="hljs-attr">backend:</span>

             <span class="hljs-attr">service:</span>

               <span class="hljs-attr">name:</span> {{ <span class="hljs-string">.Values.adminApi.appName</span> }}

               <span class="hljs-attr">port:</span>

                 <span class="hljs-attr">number:</span> {{ <span class="hljs-string">.Values.adminApi.externalPort</span> }}
</code></pre>
<h3 id="heading-admin-api-autoscaling-configuration-helm-chart">Admin-API autoscaling configuration (Helm chart)</h3>
<pre><code class="lang-yaml">{{<span class="hljs-bullet">-</span> <span class="hljs-string">if</span> <span class="hljs-string">.Values.autoscaling.enabled</span> }}

<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">autoscaling/v2beta1</span>

<span class="hljs-attr">kind:</span> <span class="hljs-string">HorizontalPodAutoscaler</span>

<span class="hljs-attr">metadata:</span>

 <span class="hljs-attr">name:</span> {{ <span class="hljs-string">include</span> <span class="hljs-string">"ks.fullname"</span> <span class="hljs-string">.</span> }}

 <span class="hljs-attr">labels:</span>

   {{<span class="hljs-bullet">-</span> <span class="hljs-string">include</span> <span class="hljs-string">"ks.labels"</span> <span class="hljs-string">.</span> <span class="hljs-string">|</span> <span class="hljs-string">nindent</span> <span class="hljs-number">4</span> }}

<span class="hljs-attr">spec:</span>

 <span class="hljs-attr">scaleTargetRef:</span>

   <span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>

   <span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>

   <span class="hljs-attr">name:</span> {{ <span class="hljs-string">include</span> <span class="hljs-string">"ks.fullname"</span> <span class="hljs-string">.</span> }}

 <span class="hljs-attr">minReplicas:</span> {{ <span class="hljs-string">.Values.autoscaling.minReplicas</span> }}

 <span class="hljs-attr">maxReplicas:</span> {{ <span class="hljs-string">.Values.autoscaling.maxReplicas</span> }}

 <span class="hljs-attr">metrics:</span>

 {{<span class="hljs-bullet">-</span> <span class="hljs-string">if</span> <span class="hljs-string">.Values.autoscaling.targetCPUUtilizationPercentage</span> }}

   <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">Resource</span>

     <span class="hljs-attr">resource:</span>

       <span class="hljs-attr">name:</span> <span class="hljs-string">cpu</span>

       <span class="hljs-attr">targetAverageUtilization:</span> {{ <span class="hljs-string">.Values.autoscaling.targetCPUUtilizationPercentage</span> }}

 {{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}

 {{<span class="hljs-bullet">-</span> <span class="hljs-string">if</span> <span class="hljs-string">.Values.autoscaling.targetMemoryUtilizationPercentage</span> }}

   <span class="hljs-bullet">-</span> <span class="hljs-attr">type:</span> <span class="hljs-string">Resource</span>

     <span class="hljs-attr">resource:</span>

       <span class="hljs-attr">name:</span> <span class="hljs-string">memory</span>

       <span class="hljs-attr">targetAverageUtilization:</span> {{ <span class="hljs-string">.Values.autoscaling.targetMemoryUtilizationPercentage</span> }}

 {{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}

{{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}
</code></pre>
<p>The "values.yml," "values-dev.yml," and "values-stage.yml" files contain the values for the templates. The environment will determine which of them is used. </p>
<p>Let's look at few samples of dev env values.</p>
<h3 id="heading-admin-api-helm-values-stageyml-file">Admin-API Helm values-stage.yml file</h3>
<pre><code class="lang-yaml"><span class="hljs-attr">env:</span> <span class="hljs-string">stage</span>

<span class="hljs-attr">appName:</span> <span class="hljs-string">admin-api</span>

<span class="hljs-attr">domain:</span> <span class="hljs-string">admin-api.xxxx.com</span>

<span class="hljs-attr">path:</span> <span class="hljs-string">/*</span>

<span class="hljs-attr">internalPort:</span> <span class="hljs-string">'80'</span>

<span class="hljs-attr">externalPort:</span> <span class="hljs-string">'80'</span>




<span class="hljs-attr">replicas:</span> <span class="hljs-number">1</span>

<span class="hljs-attr">image:</span>

 <span class="hljs-attr">repository:</span> <span class="hljs-string">xxxxxxxxx.dkr.ecr.us-east-2.amazonaws.com/admin-api</span>

 <span class="hljs-attr">pullPolicy:</span> <span class="hljs-string">Always</span>

 <span class="hljs-attr">tag:</span> <span class="hljs-string">latest</span>




<span class="hljs-attr">ingress:</span>

 <span class="hljs-attr">loadBalancerName:</span> <span class="hljs-string">project-microservices-alb</span>

 <span class="hljs-attr">tags:</span> <span class="hljs-string">Environment=stage,Kind=application</span>

 <span class="hljs-attr">certificateArn:</span> <span class="hljs-string">arn:aws:acm:us-east-2:xxxxxxxxx:certificate/xxxxxx</span>

 <span class="hljs-attr">healthcheckPath:</span> <span class="hljs-string">/healthcheck</span>

 <span class="hljs-attr">healthcheckIntervalSeconds:</span> <span class="hljs-string">'15'</span>

 <span class="hljs-attr">loadBalancerGroup:</span> <span class="hljs-string">project-microservices</span>




<span class="hljs-attr">autoscaling:</span>

 <span class="hljs-attr">enabled:</span> <span class="hljs-literal">false</span>

 <span class="hljs-attr">minReplicas:</span> <span class="hljs-number">1</span>

 <span class="hljs-attr">maxReplicas:</span> <span class="hljs-number">100</span>

 <span class="hljs-attr">targetCPUUtilizationPercentage:</span> <span class="hljs-number">80</span>




<span class="hljs-attr">env:</span>

 <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">NODE_ENV</span>

   <span class="hljs-attr">value:</span> <span class="hljs-string">stage</span>




 <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">ADMIN_PORT</span>

   <span class="hljs-attr">value:</span> <span class="hljs-string">"80</span>
</code></pre>
<p>We must upgrade the chart and restart our deployment in order for the configuration to take effect on the cluster.</p>
<p>Let's investigate the GitHub Actions steps in question.</p>
<h3 id="heading-how-to-apply-helm-configuration-in-github-actions">How to apply Helm configuration in GitHub Actions</h3>
<p>GitHub actions are CI/CD services from GitHub. They provide straightforward work processes arranged as Yaml files which run configurable blocks of code based on GitHub events. Since they are integrated into GitHub, they reduce significantly the overhead in getting a CI/CD pipeline setup.</p>
<pre><code class="lang-yaml"> <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Admin</span> <span class="hljs-string">image</span> <span class="hljs-string">build</span> <span class="hljs-string">and</span> <span class="hljs-string">push</span>

       <span class="hljs-attr">run:</span> <span class="hljs-string">|</span>

         <span class="hljs-string">docker</span> <span class="hljs-string">build</span> <span class="hljs-string">-t</span> <span class="hljs-string">project-admin-api</span> <span class="hljs-string">-f</span> <span class="hljs-string">Dockerfile.admin</span> <span class="hljs-string">.</span>

         <span class="hljs-string">docker</span> <span class="hljs-string">tag</span> <span class="hljs-string">project-admin-api</span> <span class="hljs-string">${{</span> <span class="hljs-string">env.AWS_ECR_REGISTRY</span> <span class="hljs-string">}}/project/${{</span> <span class="hljs-string">env.ENV</span> <span class="hljs-string">}}/admin-api:latest</span>

         <span class="hljs-string">docker</span> <span class="hljs-string">push</span> <span class="hljs-string">${{</span> <span class="hljs-string">env.AWS_ECR_REGISTRY</span> <span class="hljs-string">}}/project/${{</span> <span class="hljs-string">env.ENV</span> <span class="hljs-string">}}/admin-api:latest</span>




     <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Helm</span> <span class="hljs-string">upgrade</span> <span class="hljs-string">admin-api</span>

       <span class="hljs-attr">uses:</span> <span class="hljs-string">koslib/helm-eks-action@master</span>

       <span class="hljs-attr">env:</span>

         <span class="hljs-attr">KUBE_CONFIG_DATA:</span> <span class="hljs-string">${{</span> <span class="hljs-string">env.KUBE_CONFIG_DATA</span> <span class="hljs-string">}}</span>

       <span class="hljs-attr">with:</span>

         <span class="hljs-attr">command:</span> <span class="hljs-string">helm</span> <span class="hljs-string">upgrade</span> <span class="hljs-string">--install</span> <span class="hljs-string">admin-api</span> <span class="hljs-string">-n</span> <span class="hljs-string">project-${{</span> <span class="hljs-string">env.ENV</span> <span class="hljs-string">}}</span> <span class="hljs-string">charts/admin-api/</span> <span class="hljs-string">-f</span> <span class="hljs-string">charts/admin-api/values-${{</span> <span class="hljs-string">env.ENV</span> <span class="hljs-string">}}.yaml</span>




     <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Deploy</span> <span class="hljs-string">admin-api</span> <span class="hljs-string">image</span>

       <span class="hljs-attr">uses:</span> <span class="hljs-string">kodermax/kubectl-aws-eks@master</span>

       <span class="hljs-attr">env:</span>

         <span class="hljs-attr">KUBE_CONFIG_DATA:</span> <span class="hljs-string">${{</span> <span class="hljs-string">env.KUBE_CONFIG_DATA</span> <span class="hljs-string">}}</span>

       <span class="hljs-attr">with:</span>

         <span class="hljs-attr">args:</span> <span class="hljs-string">rollout</span> <span class="hljs-string">restart</span> <span class="hljs-string">deployment/admin-api-project-admin-api</span> <span class="hljs-string">--namespace=project-${{</span> <span class="hljs-string">env.ENV</span> <span class="hljs-string">}}</span>
</code></pre>
<h1 id="heading-summary">Summary</h1>
<p>In this article, we looked at infrastructure-building and Kubernetes cluster deployment steps for microservices. By using straightforward examples and avoiding further complexity with full configurations, I hope it was relatively easy to grasp. </p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/kadeniyi/">LinkedIn</a> and <a target="_blank" href="https://twitter.com/mkbadeniyi">Twitter</a></p>
<p>Hasta la vista!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Optimize Your Node.js API ]]>
                </title>
                <description>
                    <![CDATA[ In this article, I will walk you through some of the best methods to optimize APIs written in Node.js. Prerequisites To get the most out of this article, you will need an understanding of the following concepts: Node.js setup and installation How to... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-optimize-nodejs-apis/</link>
                <guid isPermaLink="false">66b9ef637bae781916c2d6e3</guid>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ optimization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kayode Adeniyi ]]>
                </dc:creator>
                <pubDate>Mon, 22 Aug 2022 17:16:36 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2022/08/pexels-ann-marie-kennon-1296000.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In this article, I will walk you through some of the best methods to optimize APIs written in Node.js.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>To get the most out of this article, you will need an understanding of the following concepts:</p>
<ul>
<li>Node.js setup and installation</li>
<li>How to build APIs with Node</li>
<li>How to use the Postman tool</li>
<li>How JavaScript async/await works</li>
<li>How to work with a basic Redis application</li>
</ul>
<h2 id="heading-what-api-optimization-actually-means">What API Optimization Actually Means</h2>
<p>Optimization involves improving the response time of your API. The shorter the response time is, the faster the API will be. </p>
<p>The tips I will share in this article will help you reduce response time, lower latency, manage errors and throughput, and minimize CPU and memory usage.</p>
<h1 id="heading-how-to-optimize-nodejs-apis">How to Optimize Node.js APIs</h1>
<h2 id="heading-1-always-use-asynchronous-functions">1. Always Use Asynchronous Functions</h2>
<p>Async functions are like the heart of JavaScript. So, the best we can do to optimize CPU usage is to write asynchronous functions to perform nonblocking I/O operations. </p>
<p>I/O operations include the processes which perform read and write data operations. It can be the database, cloud storage, or any local storage disk on which the I/O operations are performed.</p>
<p>Using asynchronous functions in an application that heavily uses I/O operations will improve it. This is because the CPU will be able to handle multiple requests simultaneously due to non-blocking I/O, while one of these requests is making an Input/Output operation.  </p>
<p>Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>);
<span class="hljs-comment">// Performing a blocking I/O</span>
<span class="hljs-keyword">var</span> file = fs.readFileSync(<span class="hljs-string">'/etc/passwd'</span>);
<span class="hljs-built_in">console</span>.log(file);
<span class="hljs-comment">// Performing a non-blocking I/O</span>
fs.readFile(<span class="hljs-string">'/etc/passwd'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, file</span>) </span>{
    <span class="hljs-keyword">if</span> (err) <span class="hljs-keyword">return</span> err;
    <span class="hljs-built_in">console</span>.log(file);
});
</code></pre>
<ul>
<li>We use the <strong>fs</strong> Node package to work with files.</li>
<li><strong>readFileSync()</strong> is synchronous and blocks execution until finished.</li>
<li><strong>readFile()</strong> is asynchronous and returns immediately while things function in the background.</li>
</ul>
<h2 id="heading-2-avoid-sessions-and-cookies-in-apis-and-send-only-data-in-the-api-response">2. Avoid Sessions and Cookies in APIs, and Send Only Data in the API Response.</h2>
<p>You use cookies and sessions to store temporary states in the server. They cost a lot for servers. </p>
<p>Now, stateless APIs are common and provide JWT, OAuth, and other authentication mechanisms. These authentication tokens are kept on the client side and protect the servers to manage the state. </p>
<p>JWT is a JSON-based security token for API Authentication. JWTs can be seen but they're not modifiable once they're sent. JWT is just serialized, not encrypted. OAuth is not an API or a service – rather, it's an open standard for authorization. OAuth is a standard set of steps for obtaining a token.</p>
<p>Also, don’t waste your time in making your Node.js server serve static files. Use NGINX and Apache instead, as they work far better than Node for this purpose. </p>
<p>While building APIs in Node, don’t send the full HTML page in the response of the API. Node servers work better when only data is sent by the API. Generally, this kind of application works with JSON data.</p>
<h2 id="heading-3-optimize-database-queries">3. Optimize Database Queries</h2>
<p>Query optimization is an essential part of building optimized APIs in Node. Especially in larger applications, you'll need to query databases many times. So, a bad query can reduce the overall performance of the application.</p>
<p>Indexing is an approach to optimize the performance of a database by minimizing the number of disk accesses required when a query is processed. It is a data structure technique that is used to quickly locate and access the data in a database. Indexes are created using a few database columns.</p>
<p>Let's say we have a DB schema without indexing and the database contains 1 million records. A simple find query will go through a larger number of records to find the matching one compared to the schema with indexing.</p>
<ul>
<li>Query without indexing:</li>
</ul>
<pre><code class="lang-js">&gt; db.user.find({<span class="hljs-attr">email</span>: <span class="hljs-string">'ofan@skyshi.com'</span>}).explain(<span class="hljs-string">"executionStats"</span>)
</code></pre>
<ul>
<li>Query with indexing:</li>
</ul>
<pre><code class="lang-js">&gt; db.getCollection(<span class="hljs-string">"user"</span>).createIndex({ <span class="hljs-string">"email"</span>: <span class="hljs-number">1</span> }, { <span class="hljs-string">"name"</span>: <span class="hljs-string">"email_1"</span>, <span class="hljs-string">"unique"</span>: <span class="hljs-literal">true</span> })
{
 <span class="hljs-string">"createdCollectionAutomatically"</span> : <span class="hljs-literal">false</span>,
 <span class="hljs-string">"numIndexesBefore"</span> : <span class="hljs-number">1</span>,
 <span class="hljs-string">"numIndexesAfter"</span> : <span class="hljs-number">2</span>,
 <span class="hljs-string">"ok"</span> : <span class="hljs-number">1</span>
}
</code></pre>
<p>There is a huge difference in the number of documents scanned ~ 1038:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Method</td><td>Documents Scanned</td></tr>
</thead>
<tbody>
<tr>
<td>Without indexing</td><td>1,039</td></tr>
<tr>
<td>With indexing</td><td>1</td></tr>
</tbody>
</table>
</div><h2 id="heading-4-optimize-apis-with-pm2-clustering"><strong>4. Optimize APIs with PM2 Clustering</strong></h2>
<p>PM2 is a production process manager designed for Node.js applications. It has a built-in load balancer and allows the application to run as multiple processes without code modifications. </p>
<p>Application downtime is almost zero using PM2. Overall, PM2 can really improve the performance and concurrency of your API. </p>
<p>Deploy the code on production and run the following command to see how the PM2 cluster has scaled on all available CPUs:</p>
<pre><code class="lang-js">pm2 start  app.js -i <span class="hljs-number">0</span>
</code></pre>
<h2 id="heading-5-reduce-ttfb-time-to-first-byte"><strong>5. Reduce TTFB (Time to First Byte)</strong></h2>
<p>Time to the first byte is a measurement used as an indication of the responsiveness of a web server or other network resource. TTFB measures the duration from the user or client making an HTTP request to the first byte of the page being received by the client's browser.</p>
<p>It is unlikely that the page all users are accessing on the web browser loads within 100ms. This is simply because of the physical distance between the server and the users.</p>
<p>Here, we can reduce the Time to First Byte by using a CDN and caching content in local data centers across the globe. This helps users access the content with minimal latency. Cloudflare is one of the CDN solutions you can use to start with.</p>
<h2 id="heading-6-use-error-scripts-with-logging"><strong>6. Use Error Scripts with Logging</strong></h2>
<p>The best way to monitor the proper functioning of your APIs is to keep track of their activity. This is where logging the data comes into play. </p>
<p>A common example of logging is printing out the logs to the console (using <code>console.log()</code>). </p>
<p>More efficient logging modules as compared to console.log are Morgan, Buyan, and Winston. Here, I’ll go with the example of Winston.</p>
<h3 id="heading-how-to-log-with-winston-features">How to log with Winston – features</h3>
<ul>
<li>Provides 4 custom levels that we can use such as info, error, verbose, debug, silly, and warn.</li>
<li>Supports querying the logs</li>
<li>Simple profiling</li>
<li>You can use multiple transports of the same type</li>
<li>Catches and logs uncaughtException</li>
</ul>
<p>You can set up Winston with the following command:</p>
<pre><code class="lang-js">npm install winston --save
</code></pre>
<p>And here's a basic configuration of Winston for logging:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> winston = <span class="hljs-built_in">require</span>(<span class="hljs-string">'winston'</span>);

<span class="hljs-keyword">let</span> logger = <span class="hljs-keyword">new</span> winston.Logger({
  <span class="hljs-attr">transports</span>: [
    <span class="hljs-keyword">new</span> winston.transports.File({
      <span class="hljs-attr">level</span>: <span class="hljs-string">'verbose'</span>,
      <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      <span class="hljs-attr">filename</span>: <span class="hljs-string">'filelog-verbose.log'</span>,
      <span class="hljs-attr">json</span>: <span class="hljs-literal">false</span>,
    }),
    <span class="hljs-keyword">new</span> winston.transports.File({
      <span class="hljs-attr">level</span>: <span class="hljs-string">'error'</span>,
      <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      <span class="hljs-attr">filename</span>: <span class="hljs-string">'filelog-error.log'</span>,
      <span class="hljs-attr">json</span>: <span class="hljs-literal">false</span>,
    })
  ]
});

logger.stream = {
  <span class="hljs-attr">write</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">message, encoding</span>) </span>{
    logger.info(message);
  }
};
</code></pre>
<h2 id="heading-7-use-http2-instead-of-http"><strong>7. Use HTTP/2 Instead of HTTP</strong></h2>
<p>In addition to these techniques, we can also apply some other techniques like using HTTP/2 over HTTP, as it has the following advantages:</p>
<ul>
<li>Multiplexing</li>
<li>Header compression</li>
<li>Server push</li>
<li>Binary format</li>
</ul>
<p>It focuses on the performance and issues that the previous version of HTTP has. It makes web browsing faster and easier and consumes less bandwidth.</p>
<h2 id="heading-8-run-tasks-in-parallel"><strong>8. Run Tasks in Parallel</strong></h2>
<p>Use <a target="_blank" href="https://caolan.github.io/async/v3/">async.js</a> to help you run tasks. Parallelizing tasks has a great impact on the performance of your API. It reduces latency and minimizes blocking operations.   </p>
<p>Parallel means running multiple things at the same time. However, when you run things in parallel, you don’t need to control the execution sequence of the program.</p>
<p>Here's a simple example using async parallel with an array:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> <span class="hljs-keyword">async</span> = <span class="hljs-built_in">require</span>(<span class="hljs-string">"async"</span>);
<span class="hljs-comment">// an example using an object instead of an array</span>
<span class="hljs-keyword">async</span>.parallel({
  <span class="hljs-attr">task1</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback</span>) </span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Task One'</span>);
      callback(<span class="hljs-literal">null</span>, <span class="hljs-number">1</span>);
    }, <span class="hljs-number">200</span>);
  },
  <span class="hljs-attr">task2</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">callback</span>) </span>{
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Task Two'</span>);
      callback(<span class="hljs-literal">null</span>, <span class="hljs-number">2</span>);
    }, <span class="hljs-number">100</span>);
    }
}, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, results</span>) </span>{
  <span class="hljs-built_in">console</span>.log(results);
  <span class="hljs-comment">// results now equals to: {task2: 2, task1: 1}</span>
});
</code></pre>
<p>In this example, we used <a target="_blank" href="https://caolan.github.io/async/v3/">async.js</a> to execute the two tasks in asynchronous mode. Task 1 requires 200 ms to complete, but task 2 does not wait for its completion – it executes at its specified delay of 100ms. </p>
<p>Parallelizing tasks has a great impact on the performance of API. It reduces latency and minimizes blocking operations.</p>
<h2 id="heading-9-use-redis-to-cache-the-app"><strong>9. Use Redis to Cache the App</strong></h2>
<p>Redis is the advanced version of Memcached. It optimizes the APIs response time by storing and retrieving the data from the main memory of the server. It increases the performance of the database queries which also reduces access latency. </p>
<p>In the following code snippets, we have called the APIs without and with Redis, respectively, and compared the response time. </p>
<p>There is a huge difference in the response time ~ 899.37ms:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Method</td><td>Response Time</td></tr>
</thead>
<tbody>
<tr>
<td>Without Redis</td><td>900ms</td></tr>
<tr>
<td>With Redis</td><td>0.621ms</td></tr>
</tbody>
</table>
</div><p>Here's Node without Redis:</p>
<pre><code class="lang-js"><span class="hljs-meta">'use strict'</span>;

<span class="hljs-comment">//Define all dependencies needed</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> responseTime = <span class="hljs-built_in">require</span>(<span class="hljs-string">'response-time'</span>)
<span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">'axios'</span>);

<span class="hljs-comment">//Load Express Framework</span>
<span class="hljs-keyword">var</span> app = express();

<span class="hljs-comment">//Create a middleware that adds a X-Response-Time header to responses.</span>
app.use(responseTime());

<span class="hljs-keyword">const</span> getBook = <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> isbn = req.query.isbn;
  <span class="hljs-keyword">let</span> url = <span class="hljs-string">`https://www.googleapis.com/books/v1/volumes?q=isbn:<span class="hljs-subst">${isbn}</span>`</span>;
  axios.get(url)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
      <span class="hljs-keyword">let</span> book = response.data.items
      res.send(book);
    })
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
      res.send(<span class="hljs-string">'The book you are looking for is not found !!!'</span>);
    });
};

app.get(<span class="hljs-string">'/book'</span>, getBook);

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Your node is running on port 3000 !!!'</span>)
});
</code></pre>
<p>And here's Node with Redis:</p>
<pre><code class="lang-js"><span class="hljs-meta">'use strict'</span>;

<span class="hljs-comment">//Define all dependencies needed</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> responseTime = <span class="hljs-built_in">require</span>(<span class="hljs-string">'response-time'</span>)
<span class="hljs-keyword">const</span> axios = <span class="hljs-built_in">require</span>(<span class="hljs-string">'axios'</span>);
<span class="hljs-keyword">const</span> redis = <span class="hljs-built_in">require</span>(<span class="hljs-string">'redis'</span>);
<span class="hljs-keyword">const</span> client = redis.createClient();

<span class="hljs-comment">//Load Express Framework</span>
<span class="hljs-keyword">var</span> app = express();

<span class="hljs-comment">//Create a middleware that adds a X-Response-Time header to responses.</span>
app.use(responseTime());

<span class="hljs-keyword">const</span> getBook = <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> isbn = req.query.isbn;
  <span class="hljs-keyword">let</span> url = <span class="hljs-string">`https://www.googleapis.com/books/v1/volumes?q=isbn:<span class="hljs-subst">${isbn}</span>`</span>;
  <span class="hljs-keyword">return</span> axios.get(url)
    .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
      <span class="hljs-keyword">let</span> book = response.data.items;
      <span class="hljs-comment">// Set the string-key:isbn in our cache. With the contents of the cache : title</span>
      <span class="hljs-comment">// Set cache expiration to 1 hour (60 minutes)</span>
      client.setex(isbn, <span class="hljs-number">3600</span>, <span class="hljs-built_in">JSON</span>.stringify(book));

      res.send(book);
    })
    .catch(<span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
      res.send(<span class="hljs-string">'The book you are looking for is not found !!!'</span>);
    });
};

<span class="hljs-keyword">const</span> getCache = <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">let</span> isbn = req.query.isbn;
  <span class="hljs-comment">//Check the cache data from the server redis</span>
  client.get(isbn, <span class="hljs-function">(<span class="hljs-params">err, result</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (result) {
      res.send(result);
    } <span class="hljs-keyword">else</span> {
      getBook(req, res);
    }
  });
}
app.get(<span class="hljs-string">'/book'</span>, getCache);

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Your node is running on port 3000 !!!'</span>)
)};
</code></pre>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this guide, we have learned how can we optimize the response time of Node.js APIs. </p>
<p>JavaScript depends heavily on functions. So, using async functions can make the script faster and non-blocking. </p>
<p>Other than this, we used cache memory (Redis), database indexing, TTFB and PM2 clustering to enhance the response times.</p>
<p>Lastly, keep in mind that it's important to pay attention to the security of the routes and make sure they're as optimized as possible. We cannot compromise a quick API response over a security loophole. So, you should keep all your standard security checks while building optimized APIs in Node.</p>
<p>Connect with me on <a target="_blank" href="https://www.linkedin.com/in/kadeniyi/">LinkedIn</a>. </p>
<p>Hasta la vista!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
