<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sowmen Rahman</title>
    <description>The latest articles on DEV Community by Sowmen Rahman (@sowmenappd).</description>
    <link>https://dev.to/sowmenappd</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F394556%2F97866441-1525-475b-9b4e-ce1b2ba0add2.png</url>
      <title>DEV Community: Sowmen Rahman</title>
      <link>https://dev.to/sowmenappd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sowmenappd"/>
    <language>en</language>
    <item>
      <title>When should you cache your APIs?</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Sun, 05 May 2024 13:51:46 +0000</pubDate>
      <link>https://dev.to/sowmenappd/understanding-when-to-cache-your-apis-2m32</link>
      <guid>https://dev.to/sowmenappd/understanding-when-to-cache-your-apis-2m32</guid>
      <description>&lt;h2&gt;
  
  
  What is caching?
&lt;/h2&gt;

&lt;p&gt;Caching is a mechanism to temporarily hold on to data returned over the network to end-user devices. There are multiple ways to implement caching, out of which the principal divisions are: client-side and server-side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client-side caching
&lt;/h2&gt;

&lt;p&gt;This is a procedure used to cache data responses from servers on the end-user’s devices. This can generally be configured into the REST API clients that are used to fetch API responses. Caching rules are configured and built into the REST API clients themselves, so the responsibility to cache and invalidate the cache rests totally on the frontend application. This method of caching is quite painless if you’re starting out on caching for some backend platforms where you’re not too bothered about maintaining the software at scale. In fact, you’ll mostly see developers prioritising using client-side caching when starting out on small/hobby projects or at small companies (mainly bootstrapping companies).&lt;/p&gt;

&lt;h2&gt;
  
  
  Server-side caching
&lt;/h2&gt;

&lt;p&gt;Caching methods deployed on your server are commonly known as server-side caching techniques. This means clients don't need to cache API responses on their end. Without a cache, an API user would make a round trip through all the functions and middlewares attached to an API controller and ultimately return the response of the controller. With caching enabled, the round-trip would be intercepted and the response stored by a cache would be returned instead, thus reducing the API latency. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cache Hit Ratio
&lt;/h2&gt;

&lt;p&gt;When a cache encounters a request by a user for the first time, it checks to determine if the key for this certain request exists in it's database. If it does, this is termed as a &lt;strong&gt;cache hit&lt;/strong&gt;. Otherwise, it is a &lt;strong&gt;cache miss&lt;/strong&gt;. The cache hit ratio is defined as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhe994nh4nyfvykzn3ae.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdhe994nh4nyfvykzn3ae.jpg" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This hit ratio is crucial for determining the efficiency of the cache server or caching logic, and is one of the most important factors you should consider when deploying a cache in front of your backend stack.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you cache your APIs?
&lt;/h2&gt;

&lt;p&gt;Now let’s assume you’re a software engineer currently managing the backend of a medium-scale company. The average load of users isn’t too high, perhaps &lt;strong&gt;7000-8000&lt;/strong&gt; users daily (in the current age of a software-driven world, we can agree that this scale is somewhat of medium or medium-large type).&lt;/p&gt;

&lt;p&gt;Given that you’re a backend engineer, chances are you’ve already faced these scenarios or at least are aware of some of the keywords in the following points: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request has timed out after 5000 ms&lt;/li&gt;
&lt;li&gt;Connection timed out, maxContentLength size of -1 exceeded&lt;/li&gt;
&lt;li&gt;Client exceeds API rate limiting quota (Error code 429)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are some of the markers that indicate it’s time to start using caching techniques. Caching reduces load on the main API servers by diverting requests to a cache storage.&lt;/p&gt;

&lt;p&gt;Today because of the importance of benefits caching brings to a software platform, there are many software implementations of cache database available, most of which are open-source and easy to deploy. The popular ones are Redis, Memcached, Varnish, etc. Popular cloud service providers like AWS, GCP, Azure, etc. provide their own dedicated caching services. However if you plan to use them, make sure to configure the storage &amp;amp; tiering options carefully, or you might end up racking up a huge bill. &lt;/p&gt;

&lt;p&gt;Caching is a brilliant technique to reduce server load but we often fail to recognise where and when it is needed. Let’s look at a few cases where it makes the most sense to use caching (server-side).&lt;/p&gt;

&lt;h2&gt;
  
  
  Read-intensive data endpoints
&lt;/h2&gt;

&lt;p&gt;API endpoints that are read-intensive benefit the most from having a cache layer. Imagine that you want to fetch the details of a user profile in your social media app. Generally, API endpoints that fetch user information do not return data that keep varying within seconds. Use caching on this type of API endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache expiry manipulation
&lt;/h2&gt;

&lt;p&gt;Caching can be done variably with respect to expiry duration. Some endpoint return data that is expected to change over short durations i.e. a few seconds, while others may return data that does not change in hours or even days. Analysing the API stats via logging, metric aggregation and the underlying data type will give you an idea of what the expiry of cache on different endpoints should be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache as a request idempotence guarantor
&lt;/h2&gt;

&lt;p&gt;API request idempotence is important for endpoints that handle interactions that should not be repeated accidentally. A good example is an API endpoint that handles payment transactions; you certainly don’t want to pay twice for a single order. And while having separate middlewares for handling API idempotence is great, a cache layer can also help with the same objective. Simply set the cache key of the request equal to the idempotence key, you’ll be good to go! Although using caching on POST/PATCH/PUT/DELETE routes seems like an anti-pattern, I wouldn’t complain if it simplifies certain tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Database caching
&lt;/h2&gt;

&lt;p&gt;Remember that if you’re working in a resource-constrained environment or in one where you want to cut costs down to the minimum value possible, using in-built database caching can work as a great alternative. Of course, it requires working with the API of the database ORM that you’ve used in your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reducing metered third-party API calls
&lt;/h2&gt;

&lt;p&gt;Your APIs can sometimes reference data from third-party APIs. Most likely than not, these third party APIs will be metered in costs. Caching the data of these metered APIs will significantly help in controlling the costs and the latency of calling the external services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed applications
&lt;/h2&gt;

&lt;p&gt;Many distributed backend use-cases can benefit from having a warmed up cache for certain data in order to lower API response times. Let’s consider an app's chat system. For each conversation you have in the app, you’d store a copy of the N most recent messages in the cache so that you don’t have to query the primary database on every user entry into the chat window. The system benefits largely if the caching action is performed on every new message received as it bypasses the need to fetch messages from the persistence layer frequently. This helps reduce the session load on a database, which is awesome!&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache key generation
&lt;/h2&gt;

&lt;p&gt;When it comes to constructing your cache keys, try to get creative with its generator functions. You should avoid including all your headers, query and path parameters, and only include those that are most likely to change when making requests. This is due to the fact that a single API request on the same endpoint can return different data based on what parameters were passed along with the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cache servers as rate limiters
&lt;/h2&gt;

&lt;p&gt;Cache storages can be used as API rate limiters. In cases where you'd like to control how many requests your backend can process in a single interval, generally per second (/s), a cache store can track the number of endpoint requests against a user token or user ID, and restrict them from accessing that endpoint till the timer resets. It is important to mention that the frontend should implement exponential backoff policy for API requests, otherwise the server load on the cache storage tends to increase rapidly.&lt;/p&gt;

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

&lt;p&gt;Caching is a very interesting subject, one which can serve a bunch of other useful scenarios (like the ones we've seen above) based on the same theoretical principals of caching requests. While it can improve the system performance of backends, it is worthwhile to note that it can produce erratic data towards end-users if the configuration isn't set correctly. Cache invalidation must be done correctly and manual invalidations may also be employed as the use-cases require, in order to ensure a seamless experience for the end-users.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>caching</category>
      <category>api</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>I built an open source app where you make friends by helping them</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Fri, 09 Jul 2021 06:52:27 +0000</pubDate>
      <link>https://dev.to/sowmenappd/introducing-helpinghand-an-open-source-social-app-where-you-make-friends-by-helping-them-4ik6</link>
      <guid>https://dev.to/sowmenappd/introducing-helpinghand-an-open-source-social-app-where-you-make-friends-by-helping-them-4ik6</guid>
      <description>&lt;p&gt;Through this post, I shall be introducing you to the making of and showcasing my open source app &lt;strong&gt;HelpingHand&lt;/strong&gt; and also talk about the brief journey of the HarperDB2021 hackathon from my perspective.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebApp link: &lt;a href="https://helpinghand.sowmenrahman.tech" rel="noopener noreferrer"&gt;https://helpinghand.sowmenrahman.tech&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  THE IDEA
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;HelpingHand&lt;/strong&gt; is an open source app that was built to serve exactly one purpose: &lt;br&gt;
&lt;strong&gt;To help people who are in need of it&lt;/strong&gt;. Every app user signs up on the app platform and then can find themselves open to helping people from various posts that the people have earlier made. This person can then reach out to these people if they feel that the post describes a problem that he/she/they can solve.&lt;/p&gt;

&lt;p&gt;But there's a catch, if you're reaching out to a person you've never interacted before, &lt;strong&gt;both of your identities are kept secret&lt;/strong&gt;, unless the post shares finds you useful and decides to make you his/her/their friend. In this way, nobody can know much about the person they are helping, unless both sides cooperate together.&lt;/p&gt;

&lt;p&gt;When a user decides to make another user their friend, they can then view their posts either help seeking posts or social posts and chat with them on the context of the post. This is basicall what HelpingHand is. You can think of HelpingHand as a cut down version of StackOverflow, but users are anonymous until both users are ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  WHY THIS IDEA?
&lt;/h2&gt;

&lt;p&gt;Ever since I was a child, I have always wanted to help people. So I guess the idea for this project naturally sprung from the urge of wanting to help people, no matter how small the contribution might be. The idea might not be that much of a good one, but I really wanted to participate in a hackathon, and this was a golden opportunity for me to showcase my skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  TECHNOLOGIES
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Frontend - React.js&lt;/li&gt;
&lt;li&gt;Backend - HarperDB integrated REST API&lt;/li&gt;
&lt;li&gt;Hosting - Vercel&lt;/li&gt;
&lt;li&gt;Version Control - GitHub&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  HRN STACK?
&lt;/h2&gt;

&lt;p&gt;If you're confused after reading the title of this post, don't question yourself because it seems like that at first. HRN would stand for HarperDB, React and Node.js. &lt;br&gt;
Now I'm pretty certain everyone's looking for the 'E' in the stack, but there isn't one.&lt;/p&gt;

&lt;p&gt;Let me give you a little backstory to why I skipped the server for this hackathon. Although this hackathon ran for a decent 30 days, I built this app on just over 7 days starting on 24th June. As I had too much academic stress from my university, I realized building both the backend and the frontend won't cut it before the deadline. Fortunately enough, HarperDB came to the rescue. &lt;/p&gt;

&lt;p&gt;Using it's awesome SQL/NoSQL integrated REST API, I was able to build the backend without needing an Express or HAPI server like I'd generally need. Don't get me wrong, this really isn't the best way of doing this, but it was the only way if I wanted to finish on time, considering the features I had planned.&lt;/p&gt;

&lt;h2&gt;
  
  
  PROJECT FEATURES
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Authentication&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Users signup as direct database users and communicate directly without the meddling of any server in between. However, this also means that people will have to create usernames that abide with the authentication rules provided by HarperDB, and it also makes the process of making batch read and writes more difficult as everything is done on the client-end. It's not ideal, I know.&lt;/p&gt;

&lt;h3&gt;
  
  
  Login page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110104813%2F1FvWB30MA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110104813%2F1FvWB30MA.png" alt="Login page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Signup page
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110211317%2Fokx277l6Y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110211317%2Fokx277l6Y.png" alt="Signup page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Post sharing
&lt;/h3&gt;

&lt;p&gt;Users are able to write posts and ask for help on the app. People can respond to these posts if they want to help them solve the problem. Posts can be of help type and social type. Only people you're friends with can see the social posts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110343646%2FpjuPw8jUz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110343646%2FpjuPw8jUz.png" alt="Post share"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Searching
&lt;/h3&gt;

&lt;p&gt;The top searchbar can be used to search for posts. Users may search targeting tags, title or description for posts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110692285%2FPMto5C_Wk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110692285%2FPMto5C_Wk.png" alt="Post search"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Messaging
&lt;/h3&gt;

&lt;p&gt;The core of the app relies on the ability to chat with people and communicate solutions for a certain type of problem. Users are able to chat with each other accordingly, but identities are kept hidden until one is satisfied with the help he/she is getting from the other person. &lt;/p&gt;

&lt;h3&gt;
  
  
  User view for public posts
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110964966%2F-ZME9gWQ2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625110964966%2F-ZME9gWQ2.png" alt="User public post view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Before a user messages a person for help response
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111010831%2FVpZy2KzRM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111010831%2FVpZy2KzRM.png" alt="Before user sends message to post"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  After a user messages a person who needs help
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111020080%2Ffvbvq3oeL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111020080%2Ffvbvq3oeL.png" alt="After user sends message to post"&gt;&lt;/a&gt;&lt;br&gt;
After this, the help seeker can decide to reply or not as he wishes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notifications
&lt;/h3&gt;

&lt;p&gt;The app also has minor notification support for when someone adds you as a friend or sends you a message. Currently, the notification system is not based on a websocket or external webhook server, and only updates on page refreshes, but these are all problems that can be mitigated with time, more on that on the roadmap talk that follows!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111433592%2FYP7CCvGlZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1625111433592%2FYP7CCvGlZ.png" alt="Notifications"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile-friendly and responsive layout
&lt;/h2&gt;

&lt;p&gt;Thanks to some very handy breakpoint hooks and responsive layout binding, I was able to make this website fully mobile responsive.&lt;/p&gt;

&lt;h2&gt;
  
  
  PROJECT ROADMAP
&lt;/h2&gt;

&lt;p&gt;As you may have realized, the project is far from completion (the fact that it's somehow working with only a week of work is amazing to me, all thanks to HarperDB). I am outlining some of the more important tasks for this project. These are however not arranged in any specific order, but however among all other things, I am seriously considering refactoring as the first priority. The tasks are&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Refactor code (A LOT)&lt;/li&gt;
&lt;li&gt;Implement clean architecture (this was a primary target, but got cut short)&lt;/li&gt;
&lt;li&gt;Enable persistence for rest of the reducers, currently only auth reducer has persistence enabled)&lt;/li&gt;
&lt;li&gt;Reduce client-side manipulation code, implement backend code for auth, and other GET and POST operations in an Express.js server&lt;/li&gt;
&lt;li&gt;Implement support for adding custom media to posts&lt;/li&gt;
&lt;li&gt;Implement websockets and mail support(depends on the server implementation)&lt;/li&gt;
&lt;li&gt;PWA (progressive web-app)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CONTRIBUTION
&lt;/h2&gt;

&lt;p&gt;I invite the community to collaborate on this open-source project, as I'll not be discarding the project after the hackathon. I shall be making changes to the UI and building the server as soon as I am able.&lt;/p&gt;

&lt;h2&gt;
  
  
  CHALLENGES
&lt;/h2&gt;

&lt;p&gt;Working with HarperDB was a very unique experience as I could manipulate the database using both SQL and NoSQL languages. The main challenge I had faced was really the time constraint compared to the project's goal weightage since I started very late. One other thing I noticed about HarperDB was that it'd not let me run nested SQL queries, it always ended up with some error I couldn't solve. However, I managed to find alternatives anyhow. Working on this project made me realize my strengths and weakness specially considering database modelling and querying. &lt;/p&gt;

&lt;h2&gt;
  
  
  LINKS
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/sowmenappd/helping-hand" rel="noopener noreferrer"&gt;Code repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helpinghand.sowmenrahman.tech%0A/" rel="noopener noreferrer"&gt;Live Website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>Understanding SOLID: Dependency Inversion Principle</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Sun, 20 Jun 2021 00:22:34 +0000</pubDate>
      <link>https://dev.to/sowmenappd/understanding-solid-dependency-inversion-principle-1i50</link>
      <guid>https://dev.to/sowmenappd/understanding-solid-dependency-inversion-principle-1i50</guid>
      <description>&lt;h2&gt;
  
  
  What is the dependency inversion principle?
&lt;/h2&gt;

&lt;p&gt;The dependency inversion principle is one of the standard guiding rules of software design and development to ensure component extensibility and loosely-coupled components.&lt;/p&gt;

&lt;p&gt;Simply said, the dependency inversion principle states that we need to rely on abstractions rather than concrete implementations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is system coupling?
&lt;/h2&gt;

&lt;p&gt;System coupling is defined as the constraining state of one item to another item inside a system. Coupling occurs on context information. For example, in an air-conditioner, the compressor is said to be coupled to the internal cooling refrigerant and cooling mechanism, since these components together make up the entirety of the cooling system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tightly-coupled vs. loosely-coupled components?
&lt;/h2&gt;

&lt;p&gt;Coupling can be of two types: &lt;strong&gt;tight coupling&lt;/strong&gt; and &lt;strong&gt;loose coupling&lt;/strong&gt;. These refer to how a system would react in presence of a substitute of a certain component/module.&lt;/p&gt;

&lt;p&gt;In our example before, if the cooling mechanism of the air condition was "tightly-coupled" to the compressor, then substitution of the compressor made by other companies are &lt;strong&gt;highly likely to break the cooling mechanism entirely&lt;/strong&gt;. This would be an example of a tightly-coupled component system. Tightly-coupled components have concrete, hard-coded implementations.&lt;/p&gt;

&lt;p&gt;Loose coupling is the &lt;em&gt;exact opposite&lt;/em&gt; of the example above, where replacement of a system with one of a similar function but of different &lt;em&gt;constitution&lt;/em&gt;/&lt;em&gt;implementation&lt;/em&gt;, will ensure that the system works as these.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's look at a code example now
&lt;/h2&gt;

&lt;p&gt;Following with our analogy from before, we define a simple &lt;strong&gt;AirConditioner&lt;/strong&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompressorV1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Compressor V1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform some necessary setup task&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// function code&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AirConditioner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Compressor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompressorV1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;powerOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;CompressorV1&lt;/strong&gt; object is a &lt;strong&gt;direct dependency&lt;/strong&gt; in this &lt;strong&gt;AirConditioner&lt;/strong&gt; class. If a new modification was to be made according to our analogy, this would break the &lt;strong&gt;AirConditioner&lt;/strong&gt; class as it doesn't have a way to extend functionality to operate with a new Compressor type. Without implementing the dependency inversion principle, this would be the future snapshot of the code, if a new compressor &lt;strong&gt;CompressorV2&lt;/strong&gt; was introduced to the air conditioner:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompressorV2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Compressor V2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform some necessary setup task&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// function code&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AirConditioner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Compressor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompressorV1&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;compressor2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CompressorV2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompressorV2&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;activeCompressor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;powerOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeCompressor&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compressor2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The problem suddenly becomes evident&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The code &lt;strong&gt;won't scale well&lt;/strong&gt; upon addition of a multitude of different components that are core dependencies in the &lt;strong&gt;AirConditioner&lt;/strong&gt; class and may need to be replaced in the future. And even if the components don't need replacement, using &lt;strong&gt;if-else&lt;/strong&gt; blocks in this way is not good for production code. It is a known fact that the more the decision branches are encountered during code execution, the slower the execution will be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inversion of control (IoC)
&lt;/h2&gt;

&lt;p&gt;From the above example, we see that the &lt;strong&gt;AirConditioner&lt;/strong&gt; class is in charge of instantiating and managing the compressor objects. This results in a tedious type of code pattern, where everytime a new &lt;strong&gt;Compressor&lt;/strong&gt; was introduced, someone would have to modify the &lt;strong&gt;AirConditioner&lt;/strong&gt; class to &lt;strong&gt;support&lt;/strong&gt; the new &lt;strong&gt;Compressor&lt;/strong&gt; type.&lt;/p&gt;

&lt;p&gt;However, let's look from a different angle. Instead of letting the &lt;strong&gt;AirConditioner&lt;/strong&gt; class handle the lifecycle of the compressor objects, we define an &lt;em&gt;abstract&lt;/em&gt; compressor interface that handles it for the &lt;strong&gt;AirConditioner&lt;/strong&gt;. We'll name this interface &lt;strong&gt;ICompressor&lt;/strong&gt; (adding an &lt;strong&gt;I&lt;/strong&gt; in front is just a naming convention for interfaces).&lt;/p&gt;

&lt;p&gt;Why an &lt;strong&gt;interface&lt;/strong&gt;, you ask? An interface allows us to &lt;em&gt;define&lt;/em&gt; a particular type of function, &lt;em&gt;without actually implementing it&lt;/em&gt;. Thus, we define an interface of a compressor that has the declaration of "setup" and "turnOn" but not the definition of it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ICompressor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each compressor class would now implement this interface. The resulting code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompressorV1&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICompressor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CompressorV1 is in system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the very same setup tasks in this interface function&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// same function code&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompressorV2&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICompressor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Compressor V2 is in system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the same necessary setup task&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// same function code as before&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moreover, the &lt;strong&gt;AirConditioner&lt;/strong&gt; class looks much cleaner with this elegant interface design:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AirConditioner&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ICompressor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;powerOn&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compressor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we were to run our program now, this is how it'd look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Main&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AirConditioner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AirConditioner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CompressorV1&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;powerOn&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What we did just now is known as &lt;strong&gt;Inversion of Control&lt;/strong&gt;. This process removes the dependency of the &lt;strong&gt;AirConditioner&lt;/strong&gt; on the &lt;strong&gt;Compressor&lt;/strong&gt; classes. So to generalize, we have &lt;strong&gt;inverted&lt;/strong&gt; the &lt;strong&gt;dependency control flow&lt;/strong&gt; where the higher level module (&lt;strong&gt;AirConditioner&lt;/strong&gt; class) was depending on the lower level module (&lt;strong&gt;CompressorV1&lt;/strong&gt; / &lt;strong&gt;CompressorV2&lt;/strong&gt; classes) by introducing an &lt;em&gt;even higher level abstraction&lt;/em&gt; (&lt;strong&gt;ICompressor&lt;/strong&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  One more example
&lt;/h2&gt;

&lt;p&gt;Now in our above air conditioner case, it is not uncommon that a complex behavior may be introduced. Suppose, a third type of compressor came along and we need to provide support for this type of compressor in our ACs as well. But the setup process for this compressor is a bit different. Unlike the first two types that had completely offline setup processes, this one has a remote connection module that is needed to be configured for the compressor system resource monitoring before the compressor can be turned on.&lt;/p&gt;

&lt;p&gt;The third compressor therefore has a different internal setup behavior as it relies on an asynchronous request to finish before its setup task can be completed.&lt;/p&gt;

&lt;p&gt;Thanks to the implementation that now uses a higher level abstration, this new type of compressor can be very easily integrated in our air conditioners. We simply implement one more &lt;strong&gt;Compressor&lt;/strong&gt; class in the following way, but this time the &lt;strong&gt;turnOn&lt;/strong&gt; function is implemented as an &lt;strong&gt;async&lt;/strong&gt; function. This is a completely valid modification as interfaces only ever care about the signature of the function and never about &lt;em&gt;how the function is implemented&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SmartCompressor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;ICompressor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Smart Compressor is in system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;loadConfiguration&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//function to load connection configuration&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the same necessary setup task&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;turnOn&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;configObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadConfiguration&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;configObject&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// function code to turn on compressor&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// catch error if connection fails&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though the process of setting up the compressor is very different this time, dependency inversion ensures this new addition will not need a complete re-iteration of our system (notice how we don't even have to touch our &lt;strong&gt;AirConditioner&lt;/strong&gt; class this time), thus saving us time and the loss of sanity. This system has now been converted to a loosely-coupled system with the help of the dependency inversion principle.&lt;/p&gt;

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

&lt;p&gt;In summary, this is what the &lt;strong&gt;Dependency Inversion Principle&lt;/strong&gt; states and intends to implement. It is clearly visible how and why loosely coupled architectures favor this principle to be staged in place and also why it made the list on the &lt;strong&gt;S.O.L.I.D&lt;/strong&gt; software design principles.&lt;/p&gt;

</description>
      <category>solidjs</category>
      <category>architecture</category>
      <category>typescript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Build a highly available Node.js application using Docker, NGINX and AWS ELB</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Thu, 15 Apr 2021 09:40:57 +0000</pubDate>
      <link>https://dev.to/sowmenappd/build-a-highly-available-node-js-application-using-docker-nginx-and-aws-elb-3cjp</link>
      <guid>https://dev.to/sowmenappd/build-a-highly-available-node-js-application-using-docker-nginx-and-aws-elb-3cjp</guid>
      <description>&lt;h1&gt;
  
  
  What is load balancing?
&lt;/h1&gt;

&lt;p&gt;Load balancing is a technique(algorithm) used to distribute incoming network traffic onto a group of servers. It provides a single entry point for all public users to a service hosted by a server. Production-grade servers are generally run behind load balancers because they can “&lt;strong&gt;even-out&lt;/strong&gt;” the incoming load across the servers, thus preventing server overloads. Load balancers also provide a secondary functionality to the servers they are routing traffic to: they act as a &lt;strong&gt;reverse proxy&lt;/strong&gt;. A reverse proxy is like a middle-man between the group of servers and the users. All requests handled by the reverse-proxy are forwarded to the appropriate server based on the request conditions. The server then responds back with its data, which is then directed to the users from the reverse proxy. In this way, r-proxies keep the identity of servers anonymous alongside preventing access to the main servers where sensitive data like configuration files, tokens, secrets, etc. are stored.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzrviivtuvpoestzuqdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuzrviivtuvpoestzuqdp.png" alt="Load balancing diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  NGINX and AWS ELB as load balancers
&lt;/h1&gt;

&lt;p&gt;NGINX is a fast and free open-source load balancer that can also act as a reverse proxy. On the other hand, ELB is a load-balancing service provide by Amazon AWS. ELB can further be of 3 main types: (1) ALB, (2) CLB and (3) NLB. A newer class of load-balancers called the gateway load-balancers have also been add into the family of cloud services AWS provides. The idea for this tutorial is to form a cascading multi load-balancer architecture that can provide a highly available Node.js server running on multiple ports.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note to users&lt;/strong&gt; : There are many ways of implementing infrastructure for Node.js applications on AWS, including ones that utilize AWS’s own ECS and ECR ecosystem for docker applications. However, this tutorial doesn’t focus on that, and aims to better understand the mechanism behind EC2 instances, load balancers and how they interact with docker over load-balanced and proxied ports.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Overview of the architecture
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0w57kfrno5e623m4gpi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0w57kfrno5e623m4gpi.png" alt="Architecture diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the architecture that we’re aiming for. Multi-level load balancers managed by AWS and NGINX which will help us maintain multiple ports on each EC2 instance for our node apps. The good thing about this architecture is that the 2 instances are in different availability zones (AZ1 and AZ2), as a result, even if one zone goes down, the other zone remains functional. And our application doesn’t crash.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Node.js app
&lt;/h1&gt;

&lt;p&gt;For the sake of simplicity, we use a standard starter Express node app, which looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx2df1qkaw3blim8vrwp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmx2df1qkaw3blim8vrwp.png" alt="index.js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ports are provided to the express app via the &lt;strong&gt;PORT&lt;/strong&gt; environment variable. We will feed these port values via Docker. This is a very simple task thanks to &lt;strong&gt;docker-compose&lt;/strong&gt;. There’s another environment variable &lt;strong&gt;SERVER_ID&lt;/strong&gt;, however don’t worry, as it’s only for demonstration purposes only. Once the whole setup is ready, the &lt;strong&gt;SERVER_ID&lt;/strong&gt; will let us know which server the load balancers are pulling the response from. This will help us to validate that our infrastructure configuration using the multi-level load-balancer/r-proxy is running the way it should be.&lt;/p&gt;

&lt;p&gt;These type of configurations are common in production pipelines. Generally the main app servers are placed in a VPC in such cases. One informational point about the load balancers is that, level 1 load balancers are often categorized as &lt;strong&gt;public-facing&lt;/strong&gt;, as they deal with the actual client requests, while those at level 2 are &lt;strong&gt;internal&lt;/strong&gt; load-balancers, whose job is to route requests between sources.&lt;/p&gt;

&lt;h1&gt;
  
  
  Launching EC2 servers
&lt;/h1&gt;

&lt;p&gt;Log in to your AWS account and go to EC2 dashboard. We will be following these steps to setup new servers and get them ready for Docker:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;From the dashboard, click on &lt;strong&gt;Launch instances&lt;/strong&gt; at the top-right corner.&lt;/li&gt;
&lt;li&gt;From the quick start section, select &lt;strong&gt;Amazon Linux 2 AMI&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose instance type &lt;strong&gt;t2.micro&lt;/strong&gt; (you can avail the free tier on this instance type if its still available on your account). You may also choose any other type you like instead.&lt;/li&gt;
&lt;li&gt;For this demonstration only, we’ll launch the 2 instances separately, since we want these two instances in different availability zones. In my case, the region is &lt;strong&gt;us-east-1&lt;/strong&gt;, so I selected the default subnet under &lt;strong&gt;us-east-1a&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Under &lt;strong&gt;User data&lt;/strong&gt; section, paste code from this script below. This will install the prerequisite software for running our node.js docker apps. &lt;/p&gt;
&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;strong&gt;Add Storage&lt;/strong&gt; and &lt;strong&gt;Add Tags&lt;/strong&gt; sections, keep the defaults and skip.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;strong&gt;Configure Security Group&lt;/strong&gt;, create a new security group with ports 22(SSH) and 80(HTTP) open. For IP range you may select &lt;strong&gt;Anywhere&lt;/strong&gt; or &lt;strong&gt;My IP*8. Since this is for testing only, you may choose either one. I went with **Anywhere&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Review and Launch&lt;/strong&gt; and then &lt;strong&gt;Launch&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new keypair to SSH into this instances. We will need this later to build the docker images for the app and the internal load balancer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first of the 2 instances have been launched now. Follow the same steps for launching the next instance, only changing the subnet to some other value than the previous one, and using the SSH keypair you created a while ago.&lt;/p&gt;

&lt;h1&gt;
  
  
  Containerizing the app and NGINX configuration
&lt;/h1&gt;

&lt;p&gt;For this tutorial, we will use this repo for the app:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Link: https://github.com/sowmenappd/load_balanced_nodejs_app


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

&lt;/div&gt;

&lt;p&gt;This will help us speed the process through. The hierarchical view of the repo is given below:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F320%2F1%2Art2Qr3QlEdFtvHML7ekGsw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F320%2F1%2Art2Qr3QlEdFtvHML7ekGsw.png" alt="Folder structure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;app&lt;/strong&gt; folder contains the node server source code along with the Dockerfile. In the &lt;strong&gt;nginx&lt;/strong&gt; folder, there is a configuration file &lt;strong&gt;nginx.conf&lt;/strong&gt; that defines the upstream server port configuration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

http{    
    upstream lb {        
        server 172.17.0.1:1000 weight=1;        
        server 172.17.0.1:2000 weight=1;        
        server 172.17.0.1:3000 weight=1;    
    }     
    server {        
        listen 80;        
        location / {            
            proxy_pass http://lb;        
        }    
    }
}


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

&lt;/div&gt;

&lt;p&gt;e configuration files specifies that the main NGINX server should listen to port 80, the &lt;strong&gt;root location&lt;/strong&gt; “/” will relay the request(proxy pass) to an upstream defined in this file named &lt;strong&gt;lb&lt;/strong&gt;. This is an upstream object that specifies how many servers will be included(these are the express servers that we mount via docker-compose, more on that in a later section), and what ports these servers will be internally running on, while the reverse proxy load balances the traffic from port 80.&lt;br&gt;
In our case, the upstream proxy will direct traffic to ports 1000, 2000, and 3000. These port numbers must match the internal PORT value that is sent to each express server instance as an env-var, which we will define in the docker-compose YAML file.&lt;br&gt;
For each of the launched instances, we do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSH into the instance using created keypair&lt;/li&gt;
&lt;li&gt;Run the following terminal commands to build the app image from its Dockerfile&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

git clone https://github.com/sowmenappd/load_balanced_nodejs_app.git
cd load_balanced_nodejs_app/app
docker build -t app .


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Next build the nginx server docker image&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd ../nginx
docker build -t nginx-s .


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

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;docker images&lt;/code&gt; and you should see something like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AFj36IiczX2Z9TXyTvS9yqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AFj36IiczX2Z9TXyTvS9yqw.png" alt="Terminal output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;For the second server, we need to change the docker-compose.yml file. The env-var &lt;strong&gt;SERVER_ID&lt;/strong&gt; should be changed to 2 for all apps (app1, app2, app3). This is definitely nothing to be concerned about, and no production server will ever have something like that. We’re doing this only for the sake of demonstration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run the final commands:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd ..
docker-compose up -d


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

&lt;/div&gt;

&lt;p&gt;Your isolated servers should now be running three process of the express app in the background. All we need now is to mount this system using the load-balancer AWS gives us, AWS ALB.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mounting the system with AWS ALB
&lt;/h1&gt;

&lt;p&gt;At this point, both the instances are ready for mounting. We are going to set up an application load balancer in AWS by following these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Navigate to &lt;strong&gt;EC2 Dashboard&lt;/strong&gt; and click on &lt;strong&gt;Target Groups&lt;/strong&gt;. Click &lt;strong&gt;Create target group&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose target type: &lt;strong&gt;Instances&lt;/strong&gt; and provide a valid target group name, and click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the two running instances and click &lt;strong&gt;Include as pending below&lt;/strong&gt;, with the port as 80.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create target group&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Next, click on &lt;strong&gt;Load balancer&lt;/strong&gt; from the side menu (left).&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create load balancer&lt;/strong&gt; and click &lt;strong&gt;Create&lt;/strong&gt; on Application Load Balancer card.&lt;/li&gt;
&lt;li&gt;In the next screen, select the availability zones you had chosen earlier while launching the instances, and proceed.&lt;/li&gt;
&lt;li&gt;Create a new security group with port 80 open to all IP range, and then click &lt;strong&gt;Next&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Existing target group&lt;/strong&gt;, and point it to the target group you created.&lt;/li&gt;
&lt;li&gt;Rest of the settings are fine, you can click on &lt;strong&gt;Create&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The load balancer should be up and running within minutes after registering the instances and getting health checks running. Now, we grab the DNS name of the load balancer from &lt;strong&gt;EC2 Dashboard &amp;gt; Load balancers&lt;/strong&gt;, copy the DNS name attribute of the load balancer.&lt;/p&gt;

&lt;p&gt;Paste the DNS name into the browser, and hit Enter. You will see that every time you refresh your browser page, the response sends back different PORT and SERVER_ID values. This validates the system because by default, NGINX and AWS load balancers use Round Robin algorithm for load balancing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2ASVhkmrpyS1dOAsJfXUj6-Q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2ASVhkmrpyS1dOAsJfXUj6-Q.gif" alt="App"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Our system is now guaranteed to be very highly available and able to withstand spiky and massive amount of traffic over prolonged durations of operation, given the multi-load balancer configuration we have deployed. As a follow up to this tutorial, I shall also post another article showing how to create and maintain a deployment pipeline that integrates with source control and deploys our changes to the servers upon commits to the GitHub repo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile reference | Docker Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;Compose file | Docker Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.html" rel="noopener noreferrer"&gt;What is an Application Load Balancer? — Elastic Load Balancing (amazon.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.html" rel="noopener noreferrer"&gt;Target groups for your Application Load Balancers — Elastic Load Balancing (amazon.com)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://faun.pub/basics-of-configuring-nginx-b38c78eb113" rel="noopener noreferrer"&gt;Basics of configuring NGINX. This article contains how to do the… | by Nethmini Romina | FAUN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>docker</category>
      <category>nginx</category>
    </item>
    <item>
      <title>Blue/Green deployment strategy</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Wed, 10 Feb 2021 07:39:51 +0000</pubDate>
      <link>https://dev.to/sowmenappd/blue-green-deployment-strategy-l5a</link>
      <guid>https://dev.to/sowmenappd/blue-green-deployment-strategy-l5a</guid>
      <description>&lt;h2&gt;
  
  
  What is blue-green deployment?
&lt;/h2&gt;

&lt;p&gt;The strategy gets its name from the idea of having two concurrent environments, and switching between environments. The environments have different code revision signatures. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;blue&lt;/strong&gt; environment is the old environment.&lt;br&gt;
The &lt;strong&gt;green&lt;/strong&gt; environment is the newer and more updated environment. &lt;/p&gt;

&lt;p&gt;Since the deployment process changes the &lt;em&gt;web pointers&lt;/em&gt; from the blue environment to the green environment, it is known as the &lt;strong&gt;Blue-Green&lt;/strong&gt; deployment strategy.&lt;/p&gt;

&lt;p&gt;Of the many benefits provided by the blue-green deployment strategy, the most important few are:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Software &amp;amp; service downtime reduction
&lt;/h3&gt;

&lt;p&gt;If production deployments relied on a single environment, there would &lt;em&gt;definitely&lt;/em&gt; be server downtime, owing to the time cost of source code updates and patches. However, if there are two environments running concurrently, this downtime gets reduced to nil given there occurs no mid-modification issues. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Experimental feature testing
&lt;/h3&gt;

&lt;p&gt;When new features need to tested publicly, this strategy offers significant advantages. Since the idea of this strategy involves having 2 environments, a small portion of the users can be exposed  to one of the environments with the experimental features. Depending on the response of the users, devs can take further decisions about the impact of the new features, change the ratio of exposure or totally upgrade to the new version.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Isolation for testing and production environments
&lt;/h3&gt;

&lt;p&gt;One of the better uses of blue-green deployment strategy is keeping the development and production environments separated from each other. Devs should never have to worry about writing new code or changing infrastructure which will directly impact the live servers. This will only cause public frustration..&lt;/p&gt;

&lt;p&gt;&lt;em&gt;..something which can easily turn into memes&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Crashes and rollbacks
&lt;/h3&gt;

&lt;p&gt;One of the more common and &lt;em&gt;mostly frightening&lt;/em&gt; term for any software company on earth would be &lt;strong&gt;crash&lt;/strong&gt;. But even though, code has been tested hundred of times before release, there might be times when a few bugs may jump out of the bucket. Critical ones. Having a blue-green deployment technique can be a life-saver during these cases, as teams can switch back to the stable older environment where those bugs are not encountered, thus giving them freedom and salvation from the torment of the public and media as they sit down to fix the bugs and redeploy again. If some different deployment technique (&lt;em&gt;in-place deployment&lt;/em&gt;) was used instead, rollbacks would become very lengthy as there would be &lt;strong&gt;&lt;em&gt;no older environment to switch back to&lt;/em&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In the industry of cloud and web tech, &lt;strong&gt;blue-green&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;canary&lt;/em&gt;&lt;/strong&gt; deployment are still one of the main and most popular deployment strategies that is used to upgrade running servers with the latest production code. Every big software company (Facebook, Google, Amazon, and so on..) has used or is still using this strategy for their deployments because of the conveniences it provides. &lt;/p&gt;

&lt;p&gt;However, a downside to this strategy is that, as the switching of the environments are handled by the &lt;em&gt;load-balancers&lt;/em&gt;, a switching time-delay due to DNS propagation occurs. DNS servers are updated with the correct server DNS names(their unique address on the web) via propagation, which means, it takes time to reach every domain name server across the planet. As a result, people of some regions of the world may not be able to access the changes in the servers as soon as the deployment happens, &lt;em&gt;because the DNS servers closest to them are still pointing to the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;older servers.&lt;/em&gt;&lt;/strong&gt; Sometimes, when a new deployment has taken place with bugs in the code, a rollback although issued instantly will not be perceived in every part of the world. &lt;em&gt;So people will still be looking at the buggy version of the software even though the buggy version has been correctly roll backed from.&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;Although these can occur, proper trial and testing can help resolve these problems before they are released to the open world. Compared to the bigger pool of advantages, these problems are easily overlooked and are the reason why blue-green deployment strategies are still preferred today.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>design</category>
      <category>aws</category>
      <category>azure</category>
    </item>
    <item>
      <title>An introduction to the theory of DevOps — why, when and how?</title>
      <dc:creator>Sowmen Rahman</dc:creator>
      <pubDate>Mon, 25 Jan 2021 18:26:39 +0000</pubDate>
      <link>https://dev.to/sowmenappd/an-introduction-to-the-theory-of-devops-why-when-and-how-110l</link>
      <guid>https://dev.to/sowmenappd/an-introduction-to-the-theory-of-devops-why-when-and-how-110l</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;So.. what’s this buzz about DevOps? It won’t kill you to know about how DevOps may save your time and sanity writing code.&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Let’s look at a dev scenario.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;It wasn’t that long ago, when coders used to write company software code, build it, then hand over the new version to the operations team for testing and debugging. The operations team would sometimes also do this ‘quality and assurance’ testing to find out how well the software would work (with or without bugs), and the potential impact of the software’s new version on the people.&lt;/p&gt;

&lt;p&gt;This process is a very lengthy process. First of all, there are two separate teams that are working on the same product, but stay completely isolated from each other; no communication between them other than in the contact periods of code finishes and dev responses, (and occasionally, probably at coffee breaks..)&lt;/p&gt;

&lt;p&gt;The developer team might not be able to use feedback properly during the interim development phase from the system operations and management team (which could have accelerated the product backlog that’s been on the agile board for what, a few weeks now?)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Now, let’s look at a different scenario.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Have you ever found yourself applying for a job (presumably a small or medium startup/firm), reading the technical skill requirements on the job post on LinkedIn, and after you get hired, and take on your first major project at the company, build a few modules, connect the backend your teammates made to the frontend you coded, and then… the project manager dumps a load of irrelevant project operations tasks that don’t seem important, at the same time have you questioning why you’re the one being assigned to this? What is my role in this company? Am I a developer or am I the sysops guy? Do I really need to code anymore or is handling the platform now my main job?&lt;/p&gt;

&lt;p&gt;If you read through that painfully long paragraph, my friend, you’re not the first one to feel that way.&lt;/p&gt;

&lt;p&gt;Having reached that stage, you might suddenly realize that maybe you lack a vast range of skills that were never asked for the job at the first place. You may have a lot of questions. But I assure you:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9u9veuvxrjr2y5now730.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9u9veuvxrjr2y5now730.jpg" alt="We’re getting there: SEPTA" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As &lt;a href="http://septa.org/"&gt;SEPTA&lt;/a&gt;’s slogan goes, so goes the cycle of software development at every software company that has ever existed. In context of the first scenario, when there’s simply too freaking much work for a seriously short deadline on the agile board, and for the second scenario, when there’s a wall of confusion in the mind of the developer regarding what stages of the product he’s supposed to be working on, DevOps is your friend.&lt;br&gt;
Leading infrastructure and IT innovation enterprise AWS terms DevOps as&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The combination of cultural philosophies, practices, and tools that increases an organization’s ability to deliver applications and services at high velocity: evolving and improving products at a faster pace than organizations using traditional software development and infrastructure management processes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or as I like to say:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;DevOps is a modern way to streamline activities in a software’s development phases in production.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;But does this solve the problems that we have in mind?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Absolutely!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You, as part of a development team will often be under enormous pressure, thanks largely to the principles of agile development. The intense focus on constantly releasing products and their subsequent newer versions to market means that you as a team member will have a limited understanding of enterprise operations and a limited concept of risk, causing you to act like a SysOps guy haphazardly and throwing yourself plus the team, into a never-ending release cycle. The concepts of validation, long-term strategy, and the business vision start to escape your grip. This results in teams like yours in the company to become so desperately focused on the day-to-day that even major technological shifts can pass them by.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Imagine how difficult this can become if you’re working in a small team, and you’re in charge of everything that needs to happen.&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Meanwhile, the operations teams in your company(in the first scenario) begin to act like development teams. They begin suggesting changes to the enterprise architecture and the production process based on issues they observe on a routine basis. Quick fixes are often applied based on a limited range of input, only to have a rollback or hotfix take place the next day. And then everything goes haywire when the solution that was implemented earlier is revealed to be the wrong one.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;The process repeats itself and generally gets worse over time and ultimately the project is ready for blast-off, destination Screwed.&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Stay careful when I say this as it applies easily to just about every business or company nowadays, whether you’re a business selling groceries or selling ads, small or large, all businesses are now dependent on IT in one way or the other. These problems are ever so common, and without a proper strategy, nobody will actual understand what’s going on or how to solve it. This gives rise to the mentality that company work often gets stressful trying to debug bugs and crashes. Now you know why this mentality catches on.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;So how does DevOps help you in light of the problems above, I hear you ask?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Earlier on, I stated that all these massive problems that occur very frequently at tech companies at scale or not, can be solved using DevOps. Yes, now we move to the core of this story.&lt;/p&gt;

&lt;p&gt;DevOps is the result of many years of software development practices, all refined to form a culture that aims to refine the cycle of software development itself.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Cool, isn’t it?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;DevOps is not a tool, but a cultural practice that intends to solve complex problems while building a software that requires developing, building, testing and deploying. Along with Q&amp;amp;A, these 4 are the core phases in the development cycles that all software releases go through. And the problem occurs when there are different teams that miscommunicate how different problems are tackled during any of the phases, like the ones we saw above.&lt;/p&gt;

&lt;p&gt;The idea of DevOps is to automate various processes in this massive cycle by breaking it up into smaller tasks, so that these do not have any complex dependency. So whenever a problem looms up in the testing phase, that problem doesn’t bog up the coding or building cycle for that matter.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H9hhfg-8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/2400/0%2AxIgSzbH0Rl-m3GQ8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H9hhfg-8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/max/2400/0%2AxIgSzbH0Rl-m3GQ8.png" alt="Software development pipeline" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The industry of software has been undergoing rapid changes regarding it’s development strategies. One of the software development strategies that we have seen above, also one of the most common strategies seen in many companies during developing production-grade software, works by separating the development and operations team. This separation can cause countless problems(as described earlier).&lt;/p&gt;

&lt;p&gt;DevOps at it’s core, aims to manage these problems by uniting the different teams on the project. These teams are no longer “&lt;strong&gt;siloed&lt;/strong&gt;” to their technical and/or operation roles. The teams start to work together and the activities of the entire application development cycle is distributed to all role-players in the company. One of the perks of doing this is that, the engineers no longer focus on only the code, but also the underlying architecture which helps them to identify and prevent problems at an early stage. The operations team on the other hand gets to interact with the code, and therefore by analyzing how the components in the app/product work can make infrastructure optimizations.&lt;/p&gt;

&lt;p&gt;To take on the advantages of DevOps, a change of mindset is necessary. A shakedown of the “no-dependency strategy” of dev and ops need to happen, for better efficiency thus, unite the teams.&lt;/p&gt;

&lt;p&gt;DevOps requires a set of tools(software) or a technology stack, that helps with the management of code and infrastructure, deployment of code and server configurations. No matter how the teams decide to choose, a useful set of tools is crucial for a good DevOps environment. Engineers can then automate processes by running small tasks, change the system specs when the software itself starts to evolve, evidently it helps the company push out product faster to the growing customer pool. These eventually become a habitual practice at the company, allowing developers and system admins to grow from their separate roles to learning a range of functions that also help them in various tasks. This increases the team’s velocity in a development cycle. A strong leadership and willingness to take responsibility of one’s own action and role in the cycle is also a key ingredient for the success of this environment. By adopting DevOps, the devs and ops teams not only work better together but progress to a unity point in the company where confusion about the product and development cycle is minimized.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloudskills</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
