<?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: Blitzcode</title>
    <description>The latest articles on DEV Community by Blitzcode (@blitzcode).</description>
    <link>https://dev.to/blitzcode</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%2F1080012%2F4257ddf2-9b9a-43a8-a52e-e8d826cbfb04.jpg</url>
      <title>DEV Community: Blitzcode</title>
      <link>https://dev.to/blitzcode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/blitzcode"/>
    <language>en</language>
    <item>
      <title>W1203: logging-fstring-interpolation (Solved)</title>
      <dc:creator>Blitzcode</dc:creator>
      <pubDate>Sun, 21 Jan 2024 07:45:59 +0000</pubDate>
      <link>https://dev.to/blitzcode/w1203-logging-fstring-interpolation-solved-3kp5</link>
      <guid>https://dev.to/blitzcode/w1203-logging-fstring-interpolation-solved-3kp5</guid>
      <description>&lt;p&gt;A few days back, I was implementing a feature, and when I was done and happy with my work, I decided to commit the code. We have enabled pre-commit hooks in our repository to maintain some coding formats and reduce the burden on the folks reviewing the code. One of the code checkers that run as part of the pre-commit check is Pylint. Pylint gave me the warning '&lt;strong&gt;logging-fstring-interpolation (W1203)'&lt;/strong&gt; and the pre-commit check kept failing. Even though I knew what needed to be done to fix the warning, being me, I could not just leave it be. I wanted to know the why part of it.&lt;/p&gt;

&lt;p&gt;Other Pylint warnings related to the logging module are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;logging-not-lazy / W1201&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;logging-format-interpolation / W1202&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pylint
&lt;/h3&gt;

&lt;p&gt;A little introduction about &lt;a href="https://pylint.readthedocs.io/en/latest/"&gt;pylint&lt;/a&gt;. Pylint is a static code analyzer, it analyses your code without actually running it. Pylint looks for potential errors, gives suggestions on coding standards that your code is not adhering to, potential places where refactoring might help, and also warnings about smelly code.&lt;/p&gt;

&lt;p&gt;Sometimes there are false positives, but you can inspect and decide for yourself whether it flagged the line incorrectly or not. If you identify it as a false positive, you can disable the pylint check for that particular line.&lt;/p&gt;

&lt;p&gt;Overall, I think it takes out a lot of pain from the reviewer to point out code smells and enforce coding standards. I would say this module has saved hours of review time.&lt;/p&gt;

&lt;h3&gt;
  
  
  logging-fstring-interpolation warning
&lt;/h3&gt;

&lt;p&gt;Python has multiple ways of string interpolation. I have explained the details of it in a previous blog - &lt;a href="https://blogs.rahultgeorge.com/string-interpolation-in-python"&gt;String Interpolation in Python&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though we are using the latest string interpolation mechanism in python, the Pylint checker is giving us a warning that there is something wrong. The official documentation for this warning says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Use another type of string formatting instead. You can use % formatting but leave interpolation to the logging function by passing the parameters as arguments.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To understand what was happening behind the hood, I wrote this code.&lt;/p&gt;

&lt;p&gt;Here, I have an Employee class with an &lt;code&gt;__str__&lt;/code&gt; magic method. The logging module is configured to log into the console and the logging level is set to DEBUG. The statements of interest are all debug statements, and I also added some headings to understand what section we are executing now.&lt;/p&gt;

&lt;p&gt;Running this code with the logging level set to DEBUG. I expect to see the str method called for all the cases because the log level is DEBUG is the lowest and all the log messages will be printed.&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%2Fuploads%2Farticles%2F62u29699g45ibm3n4qx4.png" 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%2Fuploads%2Farticles%2F62u29699g45ibm3n4qx4.png" alt="Code Time Analysis" width="767" height="554"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response is as expected. The string evaluation of the object takes place and then the log statement is evaluated.&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%2Fuploads%2Farticles%2F36p5dras7xpxvfze0529.png" 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%2Fuploads%2Farticles%2F36p5dras7xpxvfze0529.png" alt="Code Time Analysis - Response" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What if the log level is set to INFO, but the log statements are at the DEBUG level?&lt;br&gt;&lt;br&gt;
I expect the string evaluation to be deferred until the logger determines whether this log statement is above the log level set, i.e., all the statements with log level as INFO and higher will be printed whereas all the statements with log level as DEBUG will be ignored. If the log statements with DEBUG are ignored, then there is no need to call the str method of the objects.&lt;/p&gt;

&lt;p&gt;Making only 1 change on line #5, I executed the code.&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%2Fuploads%2Farticles%2Fppmpd093tihtyq6cklvg.png" 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%2Fuploads%2Farticles%2Fppmpd093tihtyq6cklvg.png" alt="Code Time Analysis - INFO mode" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The response was not something I was expecting.&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%2Fuploads%2Farticles%2Fqxriekjrtsfudnjygel0.png" 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%2Fuploads%2Farticles%2Fqxriekjrtsfudnjygel0.png" alt="Code Time Analysis - INFO mode Response" width="800" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon inspection, it was clear the evaluation of the message objects was happening irrespective of whether the statement was executed or discarded.&lt;/p&gt;

&lt;p&gt;So irrespective of what type of string interpolation I use, the order of events is as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;evaluate all the arguments to the log.debug() - this calls the str method,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Call the log.debug(),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine whether to log it or discard it.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This seemed very counterintuitive because then the logging statement when turned off will still consume time and memory. I decided to peek into the logging library. Looking at the function signature it was clear, there is nothing wrong with the library. But I am not using the library in the intended way.&lt;/p&gt;

&lt;p&gt;The intended way to use the logger function is to pass the string template as the first argument and the arguments to be substituted as *args. This way, the string interpolation happens within the logger library and not when I call the logger method.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The correct way to invoke the logging statement where the string interpolation is deferred until it is necessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Added two more lines of code and repeated the experiment. In this case, I am passing the %-formatted string template separately and the argument to substitute it with separately.&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%2Fuploads%2Farticles%2Fz5mtbrfe7sydhf73le7b.png" 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%2Fuploads%2Farticles%2Fz5mtbrfe7sydhf73le7b.png" alt="Logging Correct Syntax - INFO" width="756" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running this code again, the result is as expected, the string evaluation is not happening because the log level is set to INFO.&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%2Fuploads%2Farticles%2Ff877zj4o5zrd1tnu6xup.png" 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%2Fuploads%2Farticles%2Ff877zj4o5zrd1tnu6xup.png" alt="Logging Correct Syntax - Response" width="653" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After changing the log level to debug on line #5, the log statement is getting printed as expected.&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%2Fuploads%2Farticles%2Ftm6m3d7jo1igrykmw20o.png" 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%2Fuploads%2Farticles%2Ftm6m3d7jo1igrykmw20o.png" alt="Logging Correct Syntax - DEBUG" width="569" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the order of events will be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Call the log.debug(),&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Determine whether to log it or discard it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Discards the log because the log level is below the level set.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Evaluate the message object by substituting the arguments.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that the internal workings and the correct usage is clear, let us understand the impact of this small change on our program.&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact
&lt;/h3&gt;

&lt;p&gt;You might think this string interpolation is harmless, but if the logging statement is in a function that is called frequently and the logging level is set to be discarded during normal operation, you are wasting away a lot of execution cycles. To understand the impact, I looped the logging statements 100,000 times, collected the run time, and tabulated it.&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%2Fuploads%2Farticles%2Fzc5iargsl317bb6k9p1t.png" 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%2Fuploads%2Farticles%2Fzc5iargsl317bb6k9p1t.png" alt="Runtime comparison of various approaches" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The x-axis defines different approaches and the y-axis gives the time in milliseconds for each approach.&lt;/p&gt;

&lt;p&gt;When we are logging and the log message evaluation is expensive, using the approach of deferred evaluation can save a lot of time. When you want to turn off the debug logs and run in optimized mode. Otherwise, all the approaches are yielding similar run time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Hope this blog helps someone who is scratching their head trying to figure out why the Pylint-type checker is giving this weird warning. Pylint is trying to tell you to check your syntax because you could be committing a mistake by not using deferred evaluation. This warning message is generated when you are trying to use f-string substitution in the logging statement.&lt;/p&gt;

&lt;p&gt;Instead of simply disabling the warning, now you know the reason behind it and how to handle it the correct way.&lt;/p&gt;

&lt;p&gt;Share with me your thoughts on this in the comments! Or leave a like if you learned something new. &lt;/p&gt;

</description>
      <category>python</category>
      <category>pylint</category>
      <category>codereview</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Technical Debt - The good, bad, and the ugly.</title>
      <dc:creator>Blitzcode</dc:creator>
      <pubDate>Wed, 02 Aug 2023 07:30:00 +0000</pubDate>
      <link>https://dev.to/blitzcode/technical-debt-the-good-bad-and-the-ugly-1gj1</link>
      <guid>https://dev.to/blitzcode/technical-debt-the-good-bad-and-the-ugly-1gj1</guid>
      <description>&lt;p&gt;Let me start with some scenarios to illustrate the concept of technical debt before providing a formal definition and discussing how to eliminate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario #1
&lt;/h3&gt;

&lt;p&gt;You are part of a startup trying to ship the latest updates to the customers and your product owner is concerned if you take two days extra to document the code and add more test cases, the initial traction you have built with the customers will die down. You are accumulating technical debt. If a new teammate joins, this person will not have any references to learn from. He might modify code and may reintroduce bugs that were fixed before.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario #2
&lt;/h3&gt;

&lt;p&gt;You are part of a highly unstructured software team. The development team is involved in customer interaction and bug fixes, the team lead juggles multiple roles in the team - as the software architect, scrum master, and technical team lead. Again by not creating sustainable processes and by investing too much into one resource, you are creating a dependency. If this person leaves, or changes team, the whole knowledge is lost.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scenario #3
&lt;/h3&gt;

&lt;p&gt;If you have been part of the organization for too long and sometime in the past you and your team worked on the tool. But eventually, you have moved on and the tool is not actively maintained, and then after a year, the customer wants to add features to it. You are the only one around, but you also do not remember the requirements at that time. Also, since the tool is not maintained for a year now, the libraries are all stale. It will take as much time for you as it would take a new person to add a feature to this tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Debt - Definition
&lt;/h3&gt;

&lt;p&gt;From all the examples above, you might have gotten a fair understanding of the word "technical debt"(also known as design debt or code debt. Technical debt is the result of the software development team expediting the delivery of a certain feature or a project without proper documentation, software architecture practices, or employing resources to develop automation testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is technical debt bad?
&lt;/h3&gt;

&lt;p&gt;Technical debt is like monetary debt. It can be good or bad, depending on how it is used. If you use technical debt to create a quick and dirty proof of concept, it can be a valuable tool. However, if you use technical debt to create a system that is not scalable or maintainable, it can be a serious problem. Sooner or later, you will have to rewrite the entire system because it is not scalable, or, did not discuss the requirements properly.&lt;/p&gt;

&lt;p&gt;Like borrowed money, if you do not pay it back, it accumulates interest. Similarly, if you remember to maintain the code, refactor it when necessary, and document and write test cases, then you are keeping the yin and the yang together.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can you eliminate technical debt?
&lt;/h3&gt;

&lt;p&gt;You may not be able to completely get rid of technical debt, but you and your team can reduce the ramifications of it by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Allocating resources and prioritizing code documentation,&lt;/li&gt;
&lt;li&gt;Paying attention to testing and test case development,&lt;/li&gt;
&lt;li&gt;Refactoring the code when necessary, and,&lt;/li&gt;
&lt;li&gt;Updating libraries&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I would love to hear how your team is tackling technical debt (design debt or code debt). Do let me know in the comments!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Learning Path: MySQL Day 1</title>
      <dc:creator>Blitzcode</dc:creator>
      <pubDate>Thu, 20 Jul 2023 09:19:50 +0000</pubDate>
      <link>https://dev.to/blitzcode/learning-path-mysql-day-1-2fe7</link>
      <guid>https://dev.to/blitzcode/learning-path-mysql-day-1-2fe7</guid>
      <description>&lt;p&gt;Technically, this is not the day one. In the last few days, I took the time to create a curriculum of what I needed to learn. I explored some of the content available on the internet in the form of YouTube videos and paid courses to which I could subscribe to. The problem was these learnings will not be complete. They will only cover limited topics and I had to do my own search to gain more knowledge. &lt;/p&gt;

&lt;p&gt;Instead of identifying a single course, I decided to create a curriculum. I can learn the topics from material available on the internet. &lt;/p&gt;

&lt;p&gt;These are the topics I learned on day 1 of this journey. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connecting and disconnecting from the Server. &lt;/li&gt;
&lt;li&gt;Executing a query on the MySQL console. &lt;/li&gt;
&lt;li&gt;Creating a database&lt;/li&gt;
&lt;li&gt;Creating a table&lt;/li&gt;
&lt;li&gt;Loading data into a table. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Satisfactory start to the journey. &lt;/p&gt;

</description>
      <category>beginners</category>
      <category>100daysofcode</category>
      <category>database</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Learning Path: MySQL - Day 0</title>
      <dc:creator>Blitzcode</dc:creator>
      <pubDate>Wed, 05 Jul 2023 05:40:19 +0000</pubDate>
      <link>https://dev.to/blitzcode/learning-path-mysql-day-0-3dcf</link>
      <guid>https://dev.to/blitzcode/learning-path-mysql-day-0-3dcf</guid>
      <description>&lt;p&gt;After 10 years of being a programmer, I decided to revisit my basics of databases and learn MySQL again to brush up on my basics.  I will post about my success and failures and all the material I have referred to as I go through them. &lt;/p&gt;

&lt;h2&gt;
  
  
  What marks success at the end of the journey?
&lt;/h2&gt;

&lt;p&gt;The end goal of this journey is to take the MySQL certification and as a side goal, I want to achieve some consistency in my daily schedule. After the covid pandemic things have been going south and I get more and more demotivated to work. So, this is my way to do something to feel accomplished.  &lt;/p&gt;

&lt;p&gt;If anyone of you is interested to tag along and do a peer learning journey, ping or comment! &lt;/p&gt;

</description>
      <category>100daysofcode</category>
      <category>database</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Software Defined Networking</title>
      <dc:creator>Blitzcode</dc:creator>
      <pubDate>Fri, 19 May 2023 10:55:28 +0000</pubDate>
      <link>https://dev.to/blitzcode/software-defined-networking-2jed</link>
      <guid>https://dev.to/blitzcode/software-defined-networking-2jed</guid>
      <description>&lt;p&gt;_Disclaimer: None of the links are affiliates. _&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Before I delve into what Software-defined networking is and how I stumbled upon this. Let me explain the problem statement and all of the solutions I tried before I finally arrived at this solution. &lt;/p&gt;

&lt;p&gt;I am hoping there is another person scratching their head trying to figure out how to go about this and hope this guide saves them a lot of time. &lt;/p&gt;

&lt;h2&gt;
  
  
  Problem statement
&lt;/h2&gt;

&lt;p&gt;I have a piece of hardware (you can assume, an Arduino board and a motor driver circuit connected to the Arduino) connected to my laptop and I have a UI created in React that will allow me to control the pins of my Arduino. Let's say, I want to control the PWM output of my Arduino board, which will, in turn, modify the speed at which the motor is running. &lt;/p&gt;

&lt;p&gt;I have this react UI deployed on a &lt;a href="https://www.digitalocean.com/"&gt;digitalocean&lt;/a&gt; droplet and I wanted the UI to control the Arduino. I have written a thin flask layer between the Arduino and the React which will run on a Gunicorn server in my localhost. &lt;/p&gt;

&lt;p&gt;The solutions discussed are very much applicable to any of the Python web frameworks - FastAPI, flask, Django, and others. &lt;br&gt;
Also, to other cloud providers like Azure, AWS, and Heroku. &lt;br&gt;
Even if you want to replace the frontend with another low-code platform, that is also fine. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 1
&lt;/h2&gt;

&lt;p&gt;This was the first thing I tried. Put up an Nginx server and tried to ping from the droplet, but it failed fast. The IP address of my laptop is not visible to the public. I did not want to compromise the security, so I didn't pursue it further.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eoQ5kDO_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2ta8llxb799p8xbj0bo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eoQ5kDO_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g2ta8llxb799p8xbj0bo.jpg" alt="With Nginx" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Normally, if I wanted to run a react app with a Flask backend this is what I would do. Have my Flask server running on a digital ocean droplet and have the react application also be on digital ocean and both are on the same VPC (Virtual Private Cloud). Nginx will be front-facing the incoming traffic on the digital ocean. But here, I don't need to expose my API server to the internet since they are on the same VPC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 2
&lt;/h2&gt;

&lt;p&gt;From the first failure, I understood I wanted to bring my laptop into the same network as my digital ocean droplet. This will make my laptop visible to the droplet without causing security issues to my laptop. Naturally, VPN was my first choice. &lt;/p&gt;

&lt;p&gt;The architecture I created was to have another droplet that will act as a VPN Access server. The droplet running my react UI and the droplet running the VPN access server will be on the same VPC.  I will have to install a VPN client so that I can bring my laptop into the same network as the React UI. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iUYsMmEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xfj9l3y2lf9ch06zg7b.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iUYsMmEG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8xfj9l3y2lf9ch06zg7b.jpg" alt="With OpenVPN Server" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I had a guide from the digital ocean on how to set this up. Attaching some reference links: &lt;br&gt;
&lt;a href="https://openvpn.net/vpn-server-resources/digital-ocean-quick-start-guide/"&gt;vpn-access-server-setup&lt;/a&gt;&lt;br&gt;
&lt;a href="https://openvpn.net/vpn-server-resources/how-to-configure-the-openvpn-access-server/"&gt;how-to-configure-the-openvpn-access-server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The benefits of using such a network architecture are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Quickly extend your private networking to remote users and other sites.&lt;/li&gt;
&lt;li&gt;Create hub-and-spoke network topology, site-to-site, user-to-cloud, and various other secure VPN connections.&lt;/li&gt;
&lt;li&gt;Provide secure, remote access to applications deployed on the private cloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I did not test this out, but I can already see the pain of doing all this configuration. But I do not want to go through this for a prototype. &lt;/p&gt;

&lt;p&gt;While this experiment was not a failure, I was still searching if there was another more robust solution than this one. &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution 3
&lt;/h2&gt;

&lt;p&gt;During a brainstorming session with a colleague, he suggested why don't we use a Zero Config VPN instead of setting up a VPN Server. He suggested the name ZeroTier which actually is providing a software-defined network solution. (I will write more once I have the solution finalized) &lt;/p&gt;

&lt;p&gt;I went back to the drawing board. What ZeroTier does is, it creates a private network and gives me a network id. If I have the Zerotier client installed on my system, my system (droplet or laptop, or mobile phone) can communicate with other resources in the network. All this, while staying private. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ck7y0uHq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ql0hplpyflqscq4rzmm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ck7y0uHq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ql0hplpyflqscq4rzmm.jpg" alt="With Zerotier" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Zerotier dashboard is much easier to manage, and I get up to 25 nodes on the free tier. &lt;/p&gt;

&lt;h2&gt;
  
  
  Test Procedure and Result
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create an account on &lt;a href="https://my.zerotier.com/"&gt;Zerotier&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Step 2:&lt;/strong&gt; Create a network. &lt;br&gt;
&lt;strong&gt;Step 3:&lt;/strong&gt; Install the client on your laptop, on the droplet, or on your mobile phone. &lt;br&gt;
&lt;strong&gt;Step 4:&lt;/strong&gt; Open the Zerotier client application and click "Join a Network". key in the 16-character network id when prompted.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Step 5:&lt;/strong&gt; Go back to the Zerotier dashboard and authorize the new connection. &lt;br&gt;
&lt;strong&gt;Step 6:&lt;/strong&gt; Voila, you are done!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 7:&lt;/strong&gt; But not just yet. In my case, my flask application was listening on port 8000 and I had to go to Windows firewall settings as an administrator and create an inbound rule to allow port 8000 within the private network. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 8&lt;/strong&gt;: You can call the rest API from any device if they have joined the network! &lt;/p&gt;

&lt;p&gt;If you want more detailed documentation to setup Zerotier, check out their docs &lt;a href="https://zerotier.atlassian.net/wiki/spaces/SD/pages/8454145/Getting+Started+with+ZeroTier"&gt;here&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Going with the third approach makes sense to me for the following reason: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Less overhead on configuring the network. &lt;/li&gt;
&lt;li&gt;Security - my PC is connected to digital ocean within a private network. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Are there other solutions other than the ones I could come up with? What are the limitations or flaws of my final solution? Any other tools I can use other than Zerotier?&lt;/p&gt;

&lt;p&gt;Do let me know in the comments or drop a message on &lt;a href="https://www.linkedin.com/in/rahultgeorge05"&gt;LinkedIn&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>networking</category>
      <category>cloud</category>
      <category>python</category>
      <category>fastapi</category>
    </item>
  </channel>
</rss>
