<?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: Santosh Hari</title>
    <description>The latest articles on DEV Community by Santosh Hari (@santoshhari).</description>
    <link>https://dev.to/santoshhari</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%2F579836%2F715c5f50-a58d-4826-ae0b-45422255b950.png</url>
      <title>DEV Community: Santosh Hari</title>
      <link>https://dev.to/santoshhari</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/santoshhari"/>
    <language>en</language>
    <item>
      <title>Which Load Balancing Option(s) In Azure Should I Use?</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Fri, 23 Jun 2023 02:39:47 +0000</pubDate>
      <link>https://dev.to/santoshhari/which-load-balancing-options-in-azure-should-i-use-5847</link>
      <guid>https://dev.to/santoshhari/which-load-balancing-options-in-azure-should-i-use-5847</guid>
      <description>&lt;p&gt;Azure docs have a great page on the various &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/guide/technology-choices/load-balancing-overview"&gt;load balancing options in Azure&lt;/a&gt; that even has an &lt;a href="https://learn.microsoft.com/en-us/azure/architecture/guide/technology-choices/images/load-balancing-decision-tree.png"&gt;awesome flowchart&lt;/a&gt; summing up the choices. However, not being from a networking background, combined with Microsoft’s “special” naming, combined with some sort of memory issue recalling these names from memory meant that even if I had to rely on rote memory when in conversations with customers, I would often mix up the names. For instance, confuse traffic manager and load balancer. So, I decided to understand some of the basics behind cloud load balancers to help become a more interesting conversationalist in this topic: “well actually, you should be using an app gateway there, John”.&lt;/p&gt;

&lt;p&gt;You have 4 major options for load balancer in Azure (if you’re reading this in the year 2136, please exit now because this post is outdated af):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/frontdoor/front-door-overview"&gt;Front Door&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview"&gt;Traffic Manager&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview"&gt;Application Gateway&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/traffic-manager/traffic-manager-overview"&gt;Load Balancer&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some important concepts:&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Cloud Load Balancing?
&lt;/h3&gt;

&lt;p&gt;Load Balancing in the cloud is the process of distributing traffic and requests to multiple backend servers. The Load Balancer which does this activity sits between the Internet and cloud servers, listens to incoming requests and can distribute them on a variety of criteria including server load, geography, url route and so on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 4 versus Level 7 Load Balancing
&lt;/h3&gt;

&lt;p&gt;When reading about Load Balancers you will see references to Level 4 and Level 7. These are based on the &lt;a href="https://www.freecodecamp.org/news/osi-model-networking-layers-explained-in-plain-english/"&gt;OSI Model&lt;/a&gt; where Level 4 (L4) represents the transport layer and Level 7 (L7) represents the application layer. But what does this mean for us?&lt;/p&gt;

&lt;p&gt;Well, L4 load balancers being able to operate at a transport layer means they will be able to handle L4 protocols like TCP &lt;strong&gt;and&lt;/strong&gt; UDP. L7 being the application layer is focused on protocols built on top of these protocols (for instance: HTTP, SMTP). And since they’re at an application level, L7 load balancers can also handle “fancy” operations like security, routing, performance, and so on.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;td&gt;n/a (DNS-based routing service)&lt;/td&gt;
&lt;td&gt;L7&lt;/td&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Application Delivery – Controllers, Network and such
&lt;/h3&gt;

&lt;p&gt;In the world of networking, application delivery is the process of making an online application (global, regional, local) highly available, secure and reliable. \&lt;/p&gt;

&lt;p&gt;Load Balancing in the cloud is not just about distributing packets but also dealing with other issues like handling high transactions with minimal delay, enabling high availability and fault tolerance, and ensuring security. &lt;strong&gt;Application Delivery Controller (ADC)&lt;/strong&gt; is a load balancer that performs a subset or all of these and more. ADCs can be hardware-based (F5 Big IP, Citrix Netscaler) and/or software-based (NGINX Plus, Azure Application Gateway). Based on the features, it stands to reason that ADCs are L7 load balancers.&lt;/p&gt;

&lt;p&gt;While ADCs are capable of handling load balancing at a datacenter/regional level, global distribution requires an additional layer of complexity. Enter &lt;strong&gt;Application Delivery Network (ADN)&lt;/strong&gt;. An ADN is comprised of a &lt;strong&gt;WAN optimization controller (WOC)&lt;/strong&gt; and one or more ADCs.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ADN&lt;/td&gt;
&lt;td&gt;ADN&lt;/td&gt;
&lt;td&gt;ADC&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Global versus regional:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Global:&lt;/strong&gt; indicates presence across regions and, even, on-prem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Regional:&lt;/strong&gt; resources usually within VNETs and restricted to zonal/zone-redundant&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;Global&lt;/td&gt;
&lt;td&gt;Regional&lt;/td&gt;
&lt;td&gt;Regional (see note below)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; There is a service in preview &lt;a href="https://learn.microsoft.com/en-us/azure/load-balancer/cross-region-overview"&gt;Cross-Region Load Balancer&lt;/a&gt; that uses a global frontend public IP address that is advertised across most Azure regions, and a backend pool that contains regional load balancers&lt;/p&gt;

&lt;h3&gt;
  
  
  Protocols
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Protocol&lt;/th&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTPS&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTTP/2&lt;/td&gt;
&lt;td&gt;Supports HTTP/2 but backend is HTTP/1.1 only&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Supports Websocket and HTTP/2&lt;/td&gt;
&lt;td&gt;Supports gRPC and HTTP/2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TCP&lt;/td&gt;
&lt;td&gt;80 and 443 only&lt;/td&gt;
&lt;td&gt;All ports&lt;/td&gt;
&lt;td&gt;80 and 443 only&lt;/td&gt;
&lt;td&gt;All ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UDP&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Not supported&lt;/td&gt;
&lt;td&gt;Supported&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Web Application Firewall (WAF)
&lt;/h3&gt;

&lt;p&gt;SQL injection and cross-side scripting type vulnerabilities are the most exploited ones even in “whenever you’re reading this in the future”. WAF is a security service that protects web applications from these common exploits and vulnerabilities, such as SQL injection and cross-site scripting. It inspects (L7) the incoming traffic and can block or allow requests based on predefined or custom rules. Front Door and Application Gateway can function as WAFs&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  SSL Termination
&lt;/h3&gt;

&lt;p&gt;SSL/TLS termination is the process of decrypting the encrypted HTTPS traffic at the load balancer level, before sending it to the backend servers. This reduces the CPU load on the backend servers and improves performance, which is useful in high volume processing scenarios. Since Front Door and Application Gateway are L7, they can perform SSL termination.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h4&gt;
  
  
  Path Based Routing
&lt;/h4&gt;

&lt;p&gt;If my application had /images or /videos in the url, I want to route the request to the appropriate services/servers. Again these are L7 operations, hence supported by Front Door and Application Gateway.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Caching and Acceleration
&lt;/h3&gt;

&lt;p&gt;Again this is an L7 operation but since caching depends on geography, only Front Door can achieve this&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Health Probes
&lt;/h3&gt;

&lt;p&gt;This indicates routing based on the health and availability of backend servers and all of the above services are capable of this.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Session Affinity
&lt;/h3&gt;

&lt;p&gt;Once a connection is established, it’s more cost effective to keep it open for an extended duration. This can be achieved with usage of cookies, IP addresses and other techniques. Traffic Manager can achieve this by using IP addresses of the client, and Front and Application Gateway use user sessions.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Front Door&lt;/th&gt;
&lt;th&gt;Traffic Manager&lt;/th&gt;
&lt;th&gt;Application Gateway&lt;/th&gt;
&lt;th&gt;Load Balancer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Useful Rules of Thumb
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;For PaaS web applications, Front Door is probably the best (and often the only) load balancing option.&lt;/li&gt;
&lt;li&gt;For global non-HTTP(s) like IoT, start by considering Traffic Manager.&lt;/li&gt;
&lt;li&gt;Front Door and Traffic Manager are mutually exclusive and will never (I’m sure some “well actually” will chime in here) be used together.&lt;/li&gt;
&lt;li&gt;Application Gateways are the best fit for AKS due to &lt;a href="https://learn.microsoft.com/en-us/azure/application-gateway/ingress-controller-overview"&gt;Application Gateway Ingress Controller (AGIC)&lt;/a&gt;, a service that acts as a monitor for services in the AKS cluster and updates the Application Gateway when it detects changes.&lt;/li&gt;
&lt;li&gt;Most global architectures end up putting a Load Balancer or Application Gateway behind a Front Door or Traffic Manager.&lt;/li&gt;
&lt;li&gt;Get comfortable mixing and matching options to best suit your need with rule 3 in mind.&lt;/li&gt;
&lt;li&gt;Traffic Manager and Load Balancer &lt;strong&gt;can&lt;/strong&gt; handle HTTPs traffic, they’re simply ot the best fit.&lt;/li&gt;
&lt;li&gt;Cost: Front Door &amp;gt;&amp;gt; Application Gateway &amp;gt;&amp;gt;&amp;gt;&amp;gt; Traffic Manager &amp;gt;&amp;gt;&amp;gt; Load Balancer&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Official Azure Flowchart of selecting load balancing services
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/architecture/guide/technology-choices/load-balancing-overview"&gt;Azure Guidance on load balancing options&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2023/06/load-balancing-decision-tree.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3N8BQmtw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2023/06/load-balancing-decision-tree.png%3Fw%3D1014" alt="A decision tree showing which service to select. Use above link on guidance to learn more" width="800" height="807"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.a10networks.com/glossary/how-do-layer-4-and-layer-7-load-balancing-differ/"&gt;L4 vs L7 load balancing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/osi-model-networking-layers-explained-in-plain-english/"&gt;OSI Layers&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>network</category>
      <category>cloud</category>
      <category>architecture</category>
    </item>
    <item>
      <title>On Real Life Lessons We Can Learn From Asymmetric Warfare</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Wed, 14 Jun 2023 01:03:14 +0000</pubDate>
      <link>https://dev.to/santoshhari/on-real-life-lessons-we-can-learn-from-asymmetric-warfare-5hnf</link>
      <guid>https://dev.to/santoshhari/on-real-life-lessons-we-can-learn-from-asymmetric-warfare-5hnf</guid>
      <description>&lt;p&gt;Real life war strategies are very interesting to me, compared to randos sharing top 10 tips and tricks on LinkedIn. This is a story of a prescient book, how a major warning was ignored and almost turned the tide of World War One. In 1914, right before the war, Arthur Conan Doyle, he of Sherlock Holmes fame, was so worried about the Germans’ submarine superiority that he wrote a freaking novel about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hMflav9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2023/06/lusitania-.jpg%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hMflav9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2023/06/lusitania-.jpg%3Fw%3D450" alt="Painting of the sinking of RMS Lusitania by a U-boat in 1915" width="450" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rendering of the real life sinking of RMS Lisutania by a U-boat in 1915&lt;/p&gt;

&lt;p&gt;In Doyle’s short story Danger!, Norland a tiny country in the North Sea, gets into a war against Great Britain. The story is about how the tiny nation brings the mighty British empire to its knees with 8 submarines (U-boats)!!! The strategy was simple – the isle of Great Britain was a net importer of food and other vital supplies since the island nation could not sustain enough agriculture and other activities to support its entire population and wartime efforts.&lt;/p&gt;

&lt;p&gt;In Danger!, Norland U-boat armada Captain John Sirius (in hindsight) correctly guesses that if you starved the British isles by cutting off the shipping lanes which imported food and other essential supplies, they would have no option but to surrender. In the story, Capt Sirius essentially skips all open confrontation with the might British navy and their destroyers (hilariously named Dreadnoughts) and wages guerilla warfare at sea by concentrating on hapless merchant and supply ships with &lt;strong&gt;8 U-boats only&lt;/strong&gt;. What made this tactic unique was that marine warfare norms at that point in history (both in real life and in the book) frowned upon attacking civilian and merchant ships.&lt;/p&gt;

&lt;p&gt;The aftermath of this successful strategy is described as follows in the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the great towns starving crowds clamoured for bread before the municipal offices, and public officials everywhere were attacked and often murdered by frantic mobs, composed largely of desperate women who had seen their infants perish before their eyes. In the country, roots, bark, and weeds of every sort were used as food. In London the private mansions of Ministers were guarded by strong pickets of soldiers, while a battalion of Guards was camped permanently round the Houses of Parliament. The lives of the Prime Minister and of the Foreign Secretary were continually threatened and occasionally attempted. Yet the Government had entered upon the war with the full assent of every party in the State.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doyle’s warning was largely ignored by the British admiralty because they believed that no nation would violate the current rules of war. Sure enough, a few months after the land war in Europe, now known as World War 1 broke out, Germany went on the offensive with their U-boats and soon pivoted to include non-military ships. The British navy had no real answer to these attacks until much later in the war and at certain points risked a plight similar to the one in the book.&lt;/p&gt;

&lt;p&gt;The other prescient aspect of Doyle’s fiction was the repeated mention of a channel tunnel which would’ve established a land based route between mainland Europe and the isle to have a contingency plan. The Channel Tunnel would not open for another 80 years in real life.&lt;/p&gt;

&lt;p&gt;Some real life lessons to learn from Danger! and Norland’s strategy, when going against a superior opponent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When forced to go against an insurmountable force, avoid direct attacks – Capt Sirius avoided any direct confrontations especially against destroyers and other war ships.&lt;/li&gt;
&lt;li&gt;Avoid playing by the rules and conventions largely laid out by the enemy – It was accepted convention that civilian and merchant vessels were to be left alone. Capt Sirius knew his tiny nation stood no chance if he played by convention and directly went against it.&lt;/li&gt;
&lt;li&gt;Go for the choke points and focus on destroying them swiftly – Recognizing that the imported food supply was Great Britain’s weak point, Capt Sirius wages all-out war focused against the supply lines only.&lt;/li&gt;
&lt;li&gt;Expend only the bare minimum of resources – Capt Sirius leaves the rest of the conventional navy at home, and uses 8 swift moving and strategically placed U-boats to maximum effect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conversely, if you’re the larger force:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn to recognize your weaknesses and threats to them, however remote those threats may seem&lt;/li&gt;
&lt;li&gt;Work on contingency plans&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some interesting reads:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.arthur-conan-doyle.com/index.php?title=Danger"&gt;https://www.arthur-conan-doyle.com/index.php?title=Danger&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bbc.com/news/magazine-28954510"&gt;https://www.bbc.com/news/magazine-28954510&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://eriklarsonbooks.com/book/dead-wake/"&gt;Dead Wake&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>history</category>
      <category>strategy</category>
      <category>books</category>
    </item>
    <item>
      <title>On Asymmetric Warfare</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Mon, 12 Jun 2023 00:30:47 +0000</pubDate>
      <link>https://dev.to/santoshhari/on-asymmetric-warfare-26fj</link>
      <guid>https://dev.to/santoshhari/on-asymmetric-warfare-26fj</guid>
      <description>&lt;p&gt;Real life war strategies are very interesting to me, compared to randos sharing top 10 tips and tricks on LinkedIn. This is a story of a prescient book, how a major warning was ignored and almost turned the tide of World War One. In 1914, right before the war, Arthur Conan Doyle, he of Sherlock Holmes fame, was so worried about the Germans’ submarine superiority that he wrote a freaking novel about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hMflav9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2023/06/lusitania-.jpg%3Fw%3D450" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hMflav9N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2023/06/lusitania-.jpg%3Fw%3D450" alt="Painting of the sinking of RMS Lusitania by a U-boat in 1915" width="450" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rendering of the real life sinking of RMS Lisutania by a U-boat in 1915&lt;/p&gt;

&lt;p&gt;In Doyle’s short story Danger!, Norland a tiny country in the North Sea, gets into a war against Great Britain. The story is about how the tiny nation brings the mighty British empire to its knees with 8 submarines (U-boats)!!! The strategy was simple – the isle of Great Britain was a net importer of food and other vital supplies since the island nation could not sustain enough agriculture and other activities to support its entire population and wartime efforts.&lt;/p&gt;

&lt;p&gt;In Danger!, Norland U-boat armada Captain John Sirius (in hindsight) correctly guesses that if you starved the British isles by cutting off the shipping lanes which imported food and other essential supplies, they would have no option but to surrender. In the story, Capt Sirius essentially skips all open confrontation with the might British navy and their destroyers (hilariously named Dreadnoughts) and wages guerilla warfare at sea by concentrating on hapless merchant and supply ships with &lt;strong&gt;8 U-boats only&lt;/strong&gt;. What made this tactic unique was that marine warfare norms at that point in history (both in real life and in the book) frowned upon attacking civilian and merchant ships.&lt;/p&gt;

&lt;p&gt;The aftermath of this successful strategy is described as follows in the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the great towns starving crowds clamoured for bread before the municipal offices, and public officials everywhere were attacked and often murdered by frantic mobs, composed largely of desperate women who had seen their infants perish before their eyes. In the country, roots, bark, and weeds of every sort were used as food. In London the private mansions of Ministers were guarded by strong pickets of soldiers, while a battalion of Guards was camped permanently round the Houses of Parliament. The lives of the Prime Minister and of the Foreign Secretary were continually threatened and occasionally attempted. Yet the Government had entered upon the war with the full assent of every party in the State.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Doyle’s warning was largely ignored by the British admiralty because they believed that no nation would violate the current rules of war. Sure enough, a few months after the land war in Europe, now known as World War 1 broke out, Germany went on the offensive with their U-boats and soon pivoted to include non-military ships. The British navy had no real answer to these attacks until much later in the war and at certain points risked a plight similar to the one in the book.&lt;/p&gt;

&lt;p&gt;The other prescient aspect of Doyle’s fiction was the repeated mention of a channel tunnel which would’ve established a land based route between mainland Europe and the isle to have a contingency plan. The Channel Tunnel would not open for another 80 years in real life.&lt;/p&gt;

&lt;p&gt;Some real life lessons to learn from Danger! and Norland’s strategy, when going against a superior opponent:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When forced to go against an insurmountable force, avoid direct attacks – Capt Sirius avoided any direct confrontations especially against destroyers and other war ships.&lt;/li&gt;
&lt;li&gt;Avoid playing by the rules and conventions largely laid out by the enemy – It was accepted convention that civilian and merchant vessels were to be left alone. Capt Sirius knew his tiny nation stood no chance if he played by convention and directly went against it.&lt;/li&gt;
&lt;li&gt;Go for the choke points and focus on destroying them swiftly – Recognizing that the imported food supply was Great Britain’s weak point, Capt Sirius wages all-out war focused against the supply lines only.&lt;/li&gt;
&lt;li&gt;Expend only the bare minimum of resources – Capt Sirius leaves the rest of the conventional navy at home, and uses 8 swift moving and strategically placed U-boats to maximum effect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conversely, if you’re the larger force:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Learn to recognize your weaknesses and threats to them, however remote those threats may seem&lt;/li&gt;
&lt;li&gt;Work on contingency plans&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some interesting reads:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.arthur-conan-doyle.com/index.php?title=Danger"&gt;https://www.arthur-conan-doyle.com/index.php?title=Danger&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bbc.com/news/magazine-28954510"&gt;https://www.bbc.com/news/magazine-28954510&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://eriklarsonbooks.com/book/dead-wake/"&gt;Dead Wake&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>history</category>
      <category>books</category>
      <category>strategy</category>
    </item>
    <item>
      <title>Connectors, mavens, and salespeople for software developers</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Thu, 16 Feb 2023 12:00:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/connectors-mavens-and-salespeople-for-software-developers-3clo</link>
      <guid>https://dev.to/santoshhari/connectors-mavens-and-salespeople-for-software-developers-3clo</guid>
      <description>&lt;p&gt;In America, there is an overwhelming focus by the media on national politics which leaves people jaded to the concept of politics. I would argue that you should still be involved in local/state/national politics but that is not what this post is about. As a result of this association, politics is often a dirty word in the software development world and most software developers actively seek to avoid it. This post is about work politics and that is something that software developers should not only be cognizant about but also actively involved in.&lt;/p&gt;

&lt;p&gt;However, being involved in politics does not solely mean going full &lt;a href="https://nosweatshakespeare.com/quotes/famous/et-tu-brute/" rel="noopener noreferrer"&gt;"et tu, Brute?"&lt;/a&gt; on your colleagues. It is also the art of cultivating relationships with people at work and, maybe, over the course of multiple weeks/months/years, serendipitously leveraging that relationship to have a positive impact on the team, company and, of course, thy own self.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/d3DiXTPbqh83K/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/d3DiXTPbqh83K/giphy.gif" alt="office politics" width="500" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Dwight Schrute on workplace politics&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Software development is not just about writing code, it’s about telling the computer exactly what you want it do and then making sure that the output of this effort works for people in real life. From my experience in startups, consulting and big tech, the people part is the toughest nut to crack for software developers. But the advice and training given to software developers is also to blame for this situation. Throwing terms like &lt;em&gt;"build trust"&lt;/em&gt; and &lt;em&gt;"cultivate relationships"&lt;/em&gt; is pretty much useless without context.&lt;/p&gt;

&lt;p&gt;If you’re part of a software development team, and, are generally nice and helpful to people that is a great start. But this niceness and helpfulness could also mean you get leveraged by other people when it’s advantageous to them and not reaping the benefits (source: my personal experiences as a nice and helpful guy). Also what about working with people outside the team and with customers?&lt;/p&gt;

&lt;p&gt;This is where it helps to identify and classify people, particularly ones that can help boost the impact of your work. I first read about &lt;a href="https://en.wikipedia.org/wiki/The_Tipping_Point" rel="noopener noreferrer"&gt;connectors, mavens and salesmen in Malcolm Gladwell’s Tipping Point&lt;/a&gt;. My distaste for Malcolm Gladwell had grown over time because of his love for using anecdotes as evidence but his classification of people is still on point. Identifying the connectors, mavens and salespeople is key to doing politics at work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/QvGCMeHuP1vLYl2hLb/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/QvGCMeHuP1vLYl2hLb/giphy.gif" alt="Connector" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Connectors spark the intro&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connectors&lt;/strong&gt; are people, as the word suggests, who are ultra-connected within an organization. An easy way to identify this type of person is to seek out someone who often uses terms like "to solve X problem you should probably talk to Y person". A connector who volunteers this information freely is often the helpful kind and someone who you can go to with general problems. Once you cultivate a relationship with a connector, remember that you become part of their network and they may direct someone to you. So make sure you do not treat this as a single lane road, if you ask for help, be willing to help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l0HlMEi55YsfXyzMk/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l0HlMEi55YsfXyzMk/giphy.gif" alt="helpful librarian" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Mavens are the librarians of your organization&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mavens&lt;/strong&gt; are people who connect you with information, instead of people. Mavens are the people who often know what was said in the company town hall or know where to find obscure information regarding the organization, product, or project. They will actually read the internal documents and the monthly update emails. A helpful maven again will be seen volunteering this information and is definitely someone you can go to in order to figure out how to obtain information. Again, this is not a &lt;em&gt;"take only"&lt;/em&gt; relationship, you should be willing to voluntarily share useful information to a maven like updates in their area of interest that they may not know about yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/l2JJKs3I69qfaQleE/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/l2JJKs3I69qfaQleE/giphy.gif" alt="jedi mind trick" width="480" height="218"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Salespeople use Jedi mind tricks to get everyone to agree to their proposal&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Salespeople&lt;/strong&gt; in an this hierarchical context are persuaders. They have this magical ability to get others to agree with them without resorting to nastiness or pulling rank. An example of a salesperson would be someone who is excitedly talking about new product/technology the team should try and fast forward few weeks and the entire team is using it. What happened was the salesperson used their superpowers/Jedi mind tricks to push their agenda but also made us feel excited about adopting it. This archetype of person is harder to find in a software development setting. So once you find one, put the proverbial ring on it and never let them go. Salespeople do have a reality distortion field around them and as such we should exercise caution to make sure it does not turn into a &lt;em&gt;"give only"&lt;/em&gt; type relationship where you’re the one giving all the time.&lt;/p&gt;

&lt;p&gt;And finally, remember to both give credit if you benefit from one of these folks and also, that it is always OK to help these people and others in a pinch without expecting anything in return. Go forth and be political at work, o’ developer of the software.&lt;/p&gt;

</description>
      <category>career</category>
      <category>consultant</category>
      <category>politics</category>
      <category>software</category>
    </item>
    <item>
      <title>How to verify your GitHub account on Mastadon</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Wed, 15 Feb 2023 12:33:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/how-to-verify-your-github-account-on-mastadon-5d0</link>
      <guid>https://dev.to/santoshhari/how-to-verify-your-github-account-on-mastadon-5d0</guid>
      <description>&lt;p&gt;&lt;a href="https://www.cnet.com/tech/services-and-software/twitter-migrants-flock-to-mastodon-how-does-the-open-source-social-network-work/" rel="noopener noreferrer"&gt;Mastadon is the social media service of choice that large sections of people, techies in particular, are flocking to&lt;/a&gt; after the recent events at Twitter, mainly because it’s an non-algorithmic decentralized platform.&lt;/p&gt;

&lt;p&gt;On a related note, you can &lt;a href="https://hachyderm.io/@santoshhari" rel="noopener noreferrer"&gt;follow me on Mastadon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Verifying your GitHub on Mastadon is a 2-step process&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Paste your verification link in your GitHub Profile&lt;/li&gt;
&lt;li&gt;Paste your GitHub link in your Mastadon Profile Metadata&lt;/li&gt;
&lt;li&gt;That’s it!!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Twitter had an opaque process for verification with the previous management, and, &lt;a href="https://abcnews.go.com/Business/twitters-verification-plan-works-facing-criticism/story?id=92794983" rel="noopener noreferrer"&gt;now infamous $8 verification&lt;/a&gt; for trolls and bots with the current management&amp;gt; Mastadon, OTOH has a self verification process where you can verify yourself by posting a piece of code on a website or service. The instructions for this can be found under the &lt;strong&gt;Edit Profile&lt;/strong&gt; section as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2022/11/image-1.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.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%2Fdf9r877ji86zmi5c3pcc.png" alt="Verification: You can verify yourself as the owner of the links in your profile metadata. For that, the linked website must contain a link back to your Mastodon profile. The link back must have a rel=me attribute. The text content of the link does not matter. Here is an example:" width="598" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will work with websites where you can edit the homepage source. However, the issue with GitHub is different. The most obvious space appears to be the readme.md in the profile page. However, if you edit this page and insert the verification code, it does not work. &lt;a href="https://jan.wildeboer.net/2022/06/Quick-Fix-Verified-Mastodon-Github/" rel="noopener noreferrer"&gt;You can read a detailed explanation on why&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2022/11/image-2.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.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%2F4qbq8sdo5xdos3kppe6c.png" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The trick is to take the verification url and plug it into your profile settings directly ( &lt;strong&gt;Edit Profile&lt;/strong&gt; button on homepage) as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2022/11/image-3.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.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%2Fy6514veqwno9xk5y08k2.png" width="573" height="954"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After updating the GitHub profile with verification code, please make sure you add your GitHub link to your Mastadon &lt;strong&gt;Profile Metadata&lt;/strong&gt; as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2022/11/image-4.png" rel="noopener noreferrer"&gt;&lt;img src="https://media2.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%2Fgy33o4dce43kww45q2hb.png" width="623" height="198"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the tech crowd loves to use GitHub, why not verify on Mastadon with your GitHub profile? Please share these tips with the community.&lt;/p&gt;

</description>
      <category>technologytips</category>
      <category>github</category>
      <category>mastadon</category>
      <category>socialmedia</category>
    </item>
    <item>
      <title>Office 365 Outlook Automatic Replies – your very own vacation virtual assistant</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Mon, 16 Aug 2021 10:51:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/office-365-outlook-automatic-replies-your-very-own-vacation-virtual-assistant-139d</link>
      <guid>https://dev.to/santoshhari/office-365-outlook-automatic-replies-your-very-own-vacation-virtual-assistant-139d</guid>
      <description>&lt;p&gt;Ever go on vacation, only to be bombarded by work emails and meeting invites? What are you supposed to do? Should you respond to these invites with either&lt;/p&gt;

&lt;p&gt;a. "no" if the meeting is during the vacation, or,&lt;/p&gt;

&lt;p&gt;b. "yes" if the meeting is after vacation&lt;/p&gt;

&lt;p&gt;This means you would have to spend precious vacation time parsing through these invites figuring out if they fall within your vacation window or not. What if you had your own automated virtual assistant to take care of these bureaucratic issues while you’re on a beach sipping mojitos? Isn’t that what computers are supposed to do, instead of taking over the world like Skynet wants to?&lt;/p&gt;

&lt;p&gt;You can now let Office 365 Outlook take care of this bureaucratic business while you’re on vacation. Outlook will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Block your calendar for the duration of the vacation&lt;/li&gt;
&lt;li&gt;Automagically decline all invites sent you during your vacation that fall within your vacation window&lt;/li&gt;
&lt;li&gt;Decline any meetings you might have previously agreed to during this window, like daily standups&lt;/li&gt;
&lt;li&gt;Cancel any meetings you previously setup that falls within this window.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please note: as of publishing this post, this feature is only available on the web version of Office 365 Outlook &lt;a href="https://outlook.office.com"&gt;https://outlook.office.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Screenshots below show how to setup this up. Enjoy your vacay!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2021/08/outlook1.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u9y2MN_7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2021/08/outlook1.jpg%3Fw%3D334" alt="" width="334" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2021/08/outlook2-1.jpg"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--77UzgFAO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2021/08/outlook2-1.jpg%3Fw%3D1024" alt="" width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>technology</category>
      <category>automaticreply</category>
      <category>office365</category>
    </item>
    <item>
      <title>Using app secrets in #dotnetcore console applications</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Fri, 30 Jul 2021 08:01:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/using-app-secrets-in-dotnetcore-console-applications-4ca3</link>
      <guid>https://dev.to/santoshhari/using-app-secrets-in-dotnetcore-console-applications-4ca3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JkcX8oDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vyp9rqneb1qmz72kre0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JkcX8oDQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6vyp9rqneb1qmz72kre0.png" alt="Secret spelled out on a scrabble board" width="800" height="553"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was writing a sample dotnetcore console application for a talk because why not! I felt using a sample aspnet core web app was overkill. The app was connecting to a bunch of Azure cloud and 3rd party services (think Twilio API for SMS or LaunchDarkly API for Feature Flags) and I had to deal with connection strings.&lt;/p&gt;

&lt;p&gt;Now I have a nasty habit of "accidentally" checking in connection string and secrets into public GitHub repositories, so I wanted to do this right from the get go.&lt;/p&gt;

&lt;p&gt;I started with this official documentation on &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/extensions/configuration#configure-console-apps"&gt;adding configuration in a new .NET console application&lt;/a&gt;. To start with, add a package reference to Microsoft.Extensions.Hosting (example with dotnet cli)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft.Extensions.Hosting&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, modify Program.cs to instantiate a new instance of the HostBuilder class with pre-configured defaults&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;System.Threading.Tasks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Microsoft.Extensions.Hosting&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;Console.Example&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Program&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;IHost&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

            &lt;span class="c1"&gt;// Application code should start here.&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&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;According to the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/extensions/configuration#configure-console-apps"&gt;Microsoft docs&lt;/a&gt;, The Host.CreateDefaultBuilder(String[]) method provides default configuration for the app in the following order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ChainedConfigurationProvider : Adds an existing IConfiguration as a source.&lt;/li&gt;
&lt;li&gt;appsettings.json using the JSON configuration provider.&lt;/li&gt;
&lt;li&gt;appsettings.Environment.json using the JSON configuration provider. For example, appsettings.Production.json and appsettings.Development.json.&lt;/li&gt;
&lt;li&gt;App secrets when the app runs in the Development environment.&lt;/li&gt;
&lt;li&gt;Environment variables using the Environment Variables configuration provider.&lt;/li&gt;
&lt;li&gt;Command-line arguments using the Command-line configuration provider.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While options 1, 2, 3, 5 and 6 sound like they would work, I would really like to use option 4 since it explicitly talks about app secrets and I believe secrets should be stored separate from config. Additionally, I really liked the app secrets experience, including support for POCO, when I worked with aspnetcore web applications. So, I decided to go with option 4.&lt;/p&gt;

&lt;p&gt;But the &lt;a href="https://docs.microsoft.com/en-us/dotnet/core/extensions/configuration#configure-console-apps"&gt;Microsoft docs&lt;/a&gt; takes you a page that shows you &lt;a href="https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&amp;amp;tabs=windows"&gt;Safe storage of app secrets in development in ASP.NET Core&lt;/a&gt;. This might work but I would like to keep my application as a simple console app not a web app. Still there are some instructions that would be useful on here.&lt;/p&gt;

&lt;p&gt;The app secret values will be stored in a JSON file in the local machine’s user profile folder. For Windows this path will be &lt;em&gt;%APPDATA%\Microsoft\UserSecrets\secrets.json&lt;/em&gt; and for Linux or MacOS this path will be &lt;em&gt;~/.microsoft/usersecrets//secrets.json&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Use the Secrets Manager command line to enable secrets for the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user-secrets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This puts a guid in your .csproj file. If you take this guid and plug it into the paths above instead of , you will get access to the the secrets.json file that will store the secrets for the application, in case you want to review them during debugging. Please note, the init function will not create the file. The file will be created and modified as you continue to add and modify secrets.&lt;/p&gt;

&lt;p&gt;Next, we come up with POCO classes that can be used to map to the secrets. In this case, I split MyAppSecrets into AzureSecrets and ExternalSecrets and have dedicated sub-classes for each.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyAppSecrets&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;AzureSecrets&lt;/span&gt; &lt;span class="n"&gt;CloudSecrets&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ExternalSecrets&lt;/span&gt; &lt;span class="n"&gt;UtilitySecrets&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AzureSecrets&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;SQLConnectionString&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;CosmosConnectionString&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExternalSecrets&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;TwilioApiKey&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;}&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;LaunchDarklyApiKey&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="k"&gt;set&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;Now to add the secrets themselves. The dotnet user secrets tool does not store nested properties as proper json. Instead it uses a : to separate the properties structure. Let’s take the above POCO classes, to access SQLConnectionString, we would use TopLevelClassName:PropertyClassName:PropertyName as the secret name, for instance, MyAppSecrets:CloudSecrets:SQLConnectionString. To set a secret, you would use a dotnet cli command as below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user-secrets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MyAppSecrets:CloudSecrets:SQLConnectionString"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sqlconnstring"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repeating this for all the sub-classes and properties you could end up with a secrets.json file that looks something like below – not very readable, I know&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"MyAppSecrets:UtilitySecrets:TwilioApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"twilioconnstring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"MyAppSecrets:CloudSecrets:SQLConnectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sqlconnstring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"MyAppSecrets:CloudSecrets:CosmosConnectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cosmosdbconnstring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"MyAppSecrets:UtilitySecrets:LaunchDarklyApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launchdarklyconnstring"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have the secrets stored and the POCO class to retrieve it, app secrets should be enabled when we run the app in development environment. It turns out you can tell the HostBuilder to use a particular environment right after instantiating it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;UseEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Convenient, isn’t it? You can add and delete the &lt;em&gt;UseEnvironment("development")&lt;/em&gt; code snippet and witness for yourself how Secrets are added and removed from the list of configuration sources by debug watching the sources variable in below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;UseEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAppConfiguration&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hostingContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sources&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;But I really don’t want to have to deal with all these source since I’m only interested in the App Secrets source. I can do this using a configuration.Sources.Clear() call from the CreateHostBuilder method. Having done that I can build a configuration source for my app secrets and read it on to a static variable to use in the program as follow&lt;/p&gt;

&lt;p&gt;Add a static variable for the Program class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IConfiguration&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then modify your HostBuilder method to build an app secrets configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;        &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IHostBuilder&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateDefaultBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;UseEnvironment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"development"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureAppConfiguration&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;hostingContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sources&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="n"&gt;Configuration&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddUserSecrets&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyAppSecrets&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;Build&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;And boom goes the dynamite. Now you can use the static variable in your Main class to either access your secrets as a key value pair or by mapping it to a strongly-typed class as shown below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;IHost&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateHostBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;//mapping static variable to strongly typed class&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;appSecrets&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyAppSecrets&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyAppSecrets&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Strongly typed mapping &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;appSecrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CloudSecrets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SQLConnectionString&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;//access secrets using key value pair&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Key value pair &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"MyAppSecrets:CloudSecrets:SQLConnectionString"&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&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;But wait! There’s more. If you don’t want to have to deal with using the dotnetcore cli to enter awkwardly structured secrets like &lt;em&gt;MyAppSecrets:CloudSecrets:SQLConnectionString&lt;/em&gt;, you can modify the secrets.json file directly with properly formatted JSON value and your strongly type mapping will ensure that these values are available to you either as strongly typed class properties or config key value pairs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"MyAppSecrets"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"UtilitySecrets"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"LaunchDarklyApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launchdarklyconnstring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"TwilioApiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"twilioconnstring"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"CloudSecrets"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"SQLConnectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sqlconnstring"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"CosmosConnectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cosmosdbconnstring"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to &lt;a href="https://github.com/desinole/DotnetCoreConsoleAppSecrets"&gt;peruse the easy to read source code&lt;/a&gt;. I will add more instructions in the GitHub repo but this blog should suffice for now.&lt;/p&gt;

</description>
      <category>code</category>
      <category>coding</category>
      <category>appsecrets</category>
      <category>configuration</category>
    </item>
    <item>
      <title>OKRs – In Practice</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Wed, 03 Mar 2021 13:00:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/okrs-in-practice-3o9e</link>
      <guid>https://dev.to/santoshhari/okrs-in-practice-3o9e</guid>
      <description>&lt;p&gt;The approach in &lt;a href="https://www.goodreads.com/book/show/39286958-measure-what-matters"&gt;John Doerr’s book: Measure What Matters: How Google, Bono, and the Gates Foundation Rock the World with OKRs&lt;/a&gt; is based off Google’s OKR Playbook. While it’s good to know the practical aspects, keep in mind a good portion of the company wide practices probably only works for Google but there are some useful takeaways.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salient features of Google’s OKRs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Think big, not incremental. Don’t expect to hit them all&lt;/li&gt;
&lt;li&gt;Grading on a 0-1 color scale&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Points&lt;/th&gt;
&lt;th&gt;Color&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0.0 – 0.3&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.4 – 0.6&lt;/td&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;0.7 – 1.0&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
Google’s OKR Rating Technique



&lt;h2&gt;
  
  
  Writing effective OKRs
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Objectives == What
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;express goals and intents&lt;/li&gt;
&lt;li&gt;aggressive but realistic&lt;/li&gt;
&lt;li&gt;achievement should be no-brainer for a &lt;em&gt;rational&lt;/em&gt; observer&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Key Results == How
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;milestones adding up to achievement of objective&lt;/li&gt;
&lt;li&gt;outcomes not activities.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cross-team OKRs
&lt;/h2&gt;

&lt;p&gt;Include all teams involved in project. For instance, if Main website development, central SRE and central networking must deliver to support new SLAs for website, all three teams should have OKRs to deliver their part of the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Committed and Aspirational OKRs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Committed&lt;/th&gt;
&lt;th&gt;Aspirational&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Must deliver clear objectives or business will be impacted&lt;/td&gt;
&lt;td&gt;Future facing nebulous path, how we want the world to look&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedules and resources will be adjusted to achieve&lt;/td&gt;
&lt;td&gt;No clear idea on schedules and resources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1.0 score required to succeed. Score of less indicates errors in planning and execution&lt;/td&gt;
&lt;td&gt;0.7 score is acceptable with the idea that once teams to get to 70% they will try harder to make 100% for an aspirational objective&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Teams expected to escalate if 1.0 score is in danger&lt;/td&gt;
&lt;td&gt;Remain on team’s OKR list until completed, sometimes moved to another team with more expertise and/or bandwidth&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
Committed OKRs v. Aspirational OKRs



&lt;h2&gt;
  
  
  OKR-writing mistakes and traps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;No clear distinction between committed (keep lights on) and aspirational (this is how the world should look) OKRs. Inverting committed and aspirational OKRs also invites.&lt;/li&gt;
&lt;li&gt;Teams writing OKRs without understanding what customers want. The classic mistake is teams write OKRs believing they can achieve certain objectives by simply repeating what previously worked.&lt;/li&gt;
&lt;li&gt;Aspirational OKRs are timid, i.e., start from current state and make incremental changes. Instead ask &lt;em&gt;“What could my (or customers’) world look like in several years if freed from most constraints?”&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Team is sandbagging. Committed OKRs should consume most but not all available resource. Committed plus aspirational OKRs should consume all resources and stretch team (sounds like a recipe for burnout).&lt;/li&gt;
&lt;li&gt;Fails the &lt;em&gt;“who cares?”&lt;/em&gt; test aka Low Value Objectives (LVOs). For instance, &lt;em&gt;“increase build speeds for main website repo by 10% by Jan 1 2022”&lt;/em&gt; is a classic LVO. Instead For instance, &lt;em&gt;“increase build speeds for main website repo by 10% by Jan 1 2023 …. resulting in faster feedback to developers increasing productivity by x% enabling developers to decrease bugs by y%”&lt;/em&gt; has a clearer economic objective (dev productivity and less bugs in product).&lt;/li&gt;
&lt;li&gt;Not writing enough KRs for Os. Scoring 1.0 on all KRs should result in achievement of the O. Classic example would be an objective to improve user experience and the key results would focus on the mobile experiences but not desktop or vice versa.&lt;/li&gt;
&lt;li&gt;KRs use team internal language. For instance &lt;em&gt;“Launch Index Engine v4.1”&lt;/em&gt;. Instead use &lt;em&gt;“Launch Index Engine v4.1 to improve query performance by 25%”&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Uses business dates instead of real dates, for instance, end of quarter or end of fiscal year dates instead of actual dates for time boxing effort.&lt;/li&gt;
&lt;li&gt;Ambiguous metrics. For instance, &lt;em&gt;“support 1 million users”&lt;/em&gt;. Is it 1 million users concurrent or per day or per week?&lt;/li&gt;
&lt;li&gt;Using same OKRs for entire large groups. Instead use, high level ones for entire group but more details ones for sub-groups. Cross-team OKRs should have KRs in each sub-team.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  OKR Concepts
&lt;/h2&gt;

&lt;p&gt;The first 4 are also called the 4 superpowers in the book.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Focus and Commit to Priorities
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Run short-term (usually committed) and long-term (usually aspirational) OKRs in parallel.&lt;/li&gt;
&lt;li&gt;Rollout should start with upper management to make them accountable too. In fact, without organizational buy-in and management conviction, OKRs are bound to fail&lt;/li&gt;
&lt;li&gt;OKRs require a &lt;em&gt;shepherd&lt;/em&gt; to focus individuals on priorities.&lt;/li&gt;
&lt;li&gt;Commit 3 to 5 OKRs per cycle to prevent dilution&lt;/li&gt;
&lt;li&gt;Departmental objectives requiring support from outside should become company OKRs&lt;/li&gt;
&lt;li&gt;Each objective should be limited to max of 5 measurable, unambiguous, time-bound key results&lt;/li&gt;
&lt;li&gt;If one key result should be stretched beyond one cycle, it should go into an objectives that has similar cycles&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Align and Connect for Teamwork
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Everyone from CEO down should make their OKRs transparent. Employees should relate OKRs up to company priorities&lt;/li&gt;
&lt;li&gt;Messaging around priorities requires constant repetition&lt;/li&gt;
&lt;li&gt;Even if objectives are driven from the top, it’s important to allow flexibility on key results from frontline contributor. &lt;em&gt;Innovation dwells less at a company’s center than it’s edges&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Healthy mix of top-down and bottom-up OKRs&lt;/li&gt;
&lt;li&gt;Cross-team priorities requires horizontally shared OKRs. This should be explicit and transparent throughout the org&lt;/li&gt;
&lt;li&gt;When OKRs are modified or dropped, every stakeholder should be informed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Track for Accountability
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Continuous assessment and objective grading starting at the top. Important for leaders to take risks, sometimes fail and admit to failures publicly.&lt;/li&gt;
&lt;li&gt;Focus on measurement and less on extrinsic rewards for achievement&lt;/li&gt;
&lt;li&gt;OKR shepherd should be involved in regular check-ins&lt;/li&gt;
&lt;li&gt;Prescribed in the book: weekly 1-on-1 meetings with contributor and managers, monthly departmental meetings&lt;/li&gt;
&lt;li&gt;OKRs must evolve as necessary, even mid-cycle. Counterproductive to hold on to outdated or unrealistic goals&lt;/li&gt;
&lt;li&gt;Important to self assess and celebrate victories at end of each cycle&lt;/li&gt;
&lt;li&gt;Use public, collaborative, real-time goal setting systems (none recommended by book)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Stretch for amazing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;BHAG == Big Hairy Audacious Goal aka aspirational&lt;/li&gt;
&lt;li&gt;Important to separate committed goals and BHAGs&lt;/li&gt;
&lt;li&gt;Risks and failures in short cycles should be encouraged for quick feedback&lt;/li&gt;
&lt;li&gt;All goals should stretch even if some risk not being met&lt;/li&gt;
&lt;li&gt;Replace incremental OKRs with exponential ones. 10x (now toxic) comes from this&lt;/li&gt;
&lt;li&gt;Stretch goals could be rolled to next cycle, on a reasonable basis&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Continuous Performance Management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Move from annual performance management to continuous performance management. This is necessary to monitor and address issues throughout the cycle&lt;/li&gt;
&lt;li&gt;Tying goal attainment to bonus checks will cause sandbagging and risk-averse behavior&lt;/li&gt;
&lt;li&gt;Important for performance evaluations to be transparent and catering to an individuals strengths and ambition&lt;/li&gt;
&lt;li&gt;Motivate intrinsically with purposeful work and opportunities for growth&lt;/li&gt;
&lt;li&gt;Implement ongoing CFRs (conversations, feedback and recognition) along with structured goal setting&lt;/li&gt;
&lt;li&gt;Contributor should set the agenda for performance conversations. Manager should learn and coach&lt;/li&gt;
&lt;li&gt;Performance feedback should be unconstrained by org chart. Leverage anonymous surveys for real-time feedback&lt;/li&gt;
&lt;li&gt;Provide opportunities for peer feedback and peer recognition&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Importance of Culture
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Align top-line OKRs with org values&lt;/li&gt;
&lt;li&gt;Values should be conveyed by deeds, words are cheap&lt;/li&gt;
&lt;li&gt;For collective objectives, assign key results to individuals&lt;/li&gt;
&lt;li&gt;Promote opportunities for interpersonal/volunteer support for additional help on actions&lt;/li&gt;
&lt;li&gt;Address issues around accountability and trust before rolling out OKRs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample OKR cycle
&lt;/h2&gt;

&lt;p&gt;Settings OKRs at company, team and individual levels&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;4-6 weeks before quarter: Leadership brainstorms top-line OKRs for company.&lt;/li&gt;
&lt;li&gt;2 weeks before quarter: Communicate output of step 1 company-wide&lt;/li&gt;
&lt;li&gt;Start of quarter: Teams develop own OKRs to align with top-line OKRs&lt;/li&gt;
&lt;li&gt;1 week after start of quarter: Individual employees share their own OKRs in 1-on-1 settings with manager to make sure they’re aligned at the team and company level.&lt;/li&gt;
&lt;li&gt;Throughout quarter: Individual employees measure and share progress with regular check-ins with managers. This is a time to assess the progress and re-calibrate, if needed.&lt;/li&gt;
&lt;li&gt;Before end of quarter: Individual employees score their OKRs, self assess and reflect on accomplishment.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Sample OKRs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; Improve web service SLA to 4 nines&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 1&lt;/strong&gt; Launch v4.1 web service by March 30 with updates for stability&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 2&lt;/strong&gt; 100ms response time for web service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 3&lt;/strong&gt; 99.99% uptime for web service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 4&lt;/strong&gt; Add regional redundancy for web service&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>goals</category>
      <category>okr</category>
    </item>
    <item>
      <title>Don’t just say hello in chat</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Thu, 25 Feb 2021 14:00:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/don-t-just-say-hello-in-chat-46fo</link>
      <guid>https://dev.to/santoshhari/don-t-just-say-hello-in-chat-46fo</guid>
      <description>&lt;p&gt;So the official &lt;a href="https://twitter.com/microsoft"&gt;Microsoft Twitter&lt;/a&gt; account dropped a tweet that deeply resonated with me.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Please don’t just say hello in chat.&lt;/p&gt;

&lt;p&gt;— Microsoft (@Microsoft) &lt;a href="https://twitter.com/Microsoft/status/1364712460452773897?ref_src=twsrc%5Etfw"&gt;February 24, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So what’s wrong with just saying hello in chat? For context, this assumes business chat like Teams or Slack. Well, consider the below exchange that happened earlier this week – Monday and Tuesday (aka Yesterday in below screenshot) – between me and a collaborator on a project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://santoshhari.files.wordpress.com/2021/02/image-1.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HB5pVGQX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2021/02/image-1.png%3Fw%3D951" alt="" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A collaborator (West Coast) messaged me (East Coast) after hours (for me) with a "Hi" and no context. I generally don’t respond to chat messages after hours unless someone tags it "Urgent" or "Important" – as is our standing team policy. Well, as you can gather from above exchange, I did not respond until nearly 15 hours after the initial message was posted and it took another 3 hours to arrive at the context "something was not/working". As we work remote (and global), asynchronous communication is not only important but also necessary. But asynchronous communication only works if we give it context. We’re hardwired to be polite but saying "hi" in chat and then waiting 18 hours to provide context is a recipe for failure when it comes to asynchronous communication. Other forms of saying "hello" in chat:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Hello X, got a minute?" (Instead: "Hello X, if have a minute can you please take a look at X?")&lt;/li&gt;
&lt;li&gt;"Hey! I have a quick question" (Instead: "Hey! &lt;em&gt;followed by actual question&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more examples, read &lt;a href="https://www.nohello.com/"&gt;nohello.com&lt;/a&gt;. On a related note, I find people who use &lt;em&gt;nohello&lt;/em&gt; as a permanent status on their chat as a little rude. So what is the solution? A passive aggressive chat bot that responds to Hi with a gif? Chime in with thoughts below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/xT9IgG50Fb7Mi0prBC/giphy.gif" width="400" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On a lighter note, that tweet evoked a hearty agreement from me, which lead to this hilarious exchange culminating in a response from the official Microsoft Twitter account. Always a good day when that happens.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You're welcome.&lt;/p&gt;

&lt;p&gt;— Microsoft (@Microsoft) &lt;a href="https://twitter.com/Microsoft/status/1364732487008616451?ref_src=twsrc%5Etfw"&gt;February 25, 2021&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Intro to OKRs</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Mon, 22 Feb 2021 13:00:00 +0000</pubDate>
      <link>https://dev.to/santoshhari/intro-to-okrs-2d69</link>
      <guid>https://dev.to/santoshhari/intro-to-okrs-2d69</guid>
      <description>&lt;p&gt;These are my notes from reading &lt;a href="https://www.goodreads.com/book/show/39286958-measure-what-matters"&gt;John Doerr’s book: Measure What Matters: How Google, Bono, and the Gates Foundation Rock the World with OKRs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are OKRs?
&lt;/h2&gt;

&lt;p&gt;OKRs as defined in the book:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A management methodology that helps to ensure that the company focuses efforts on the same important issues throughout the organization.&lt;/p&gt;

&lt;p&gt;&lt;cite&gt;John Doerr: Measure What Matters&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Who can use OKRs?
&lt;/h2&gt;

&lt;p&gt;While the term OKR, which probably originated at Google, was largely used for organizational goal settings and related actions, this technique can be used by organizations of any size and even individuals. Understanding OKRs and helping implementing them can also prove useful for non-leadership rung employees since this can help measure your impact on the organizational goals.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to do OKRs?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Objectives = many Key Results&lt;/li&gt;
&lt;li&gt;Objective (1)–&amp;gt;(has many) Key Results.&lt;/li&gt;
&lt;li&gt;OKRs are a management methodology to ensure focus on same issues company-wide.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Objectives&lt;/th&gt;
&lt;th&gt;Key Results&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;– “WHAT is to be achieved, no more no less”&lt;/td&gt;
&lt;td&gt;– “benchmark and monitor HOW we get to the objective”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;– significant, concrete, action oriented, and (ideally) inspirational&lt;/td&gt;
&lt;td&gt;– specific, time-bound, aggressive yet realistic, measurable and verifiable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;– long lived, often year or more, can be rolled over&lt;/td&gt;
&lt;td&gt;– quarter or less, evolve as work progresses&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
Comparing Objectives and Key Results



&lt;p&gt;Objective = sum of all Key Results, if all key results achieved then objective should be complete&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a Sample OKR look like?
&lt;/h2&gt;

&lt;p&gt;Express a clear objective and follow it up with measurable key results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Objective&lt;/strong&gt; Improve web service SLA to 4 nines&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 1&lt;/strong&gt; Launch v4.1 web service by March 30 with updates for redundancy and stability&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 2&lt;/strong&gt; 100ms response time for hosting platform&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 3&lt;/strong&gt; 99.99% uptime&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Result 4&lt;/strong&gt; Add regional redundancy&lt;/p&gt;

&lt;h2&gt;
  
  
  Book Summary
&lt;/h2&gt;

&lt;p&gt;The book is divided into 3 parts: superpowers, applications and methodology&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1: Superpowers
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Focus and commit to priorities: OKRs focus teams and companies on work that’s important and reject superfluous work. This forces leaders to make hard choices on priorities. Removes any lingering confusion on what people are supposed to be working on.&lt;/li&gt;
&lt;li&gt;Align and connect: OKRs should be transparent throughout the org. Individuals should link their OKRs up to team and teams should link up to company and sideways to cross-dependencies with other teams.&lt;/li&gt;
&lt;li&gt;Track for accountability: OKRs are data driven and enforce periodic check-ins, objective grading and continuous reassessment. The most important part is that any key result that is in danger triggers action to put it on track or be revised/replaced, if necessary.&lt;/li&gt;
&lt;li&gt;Stretch for amazing: By focusing, align and tracking, OKRs motivated people and companies to overperform.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Part 2: Applications
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;CFRs: Conversation, Feedback and Recognition add up to &lt;em&gt;“continuous performance management”&lt;/em&gt;, a replacement for annual performance reviews.&lt;/li&gt;
&lt;li&gt;Continuous Improvement: Structured goal setting and continuous performance management help organizations on the long road to operational excellence by improving one day at a time.&lt;/li&gt;
&lt;li&gt;Importance of culture: OKRs and CFRs aim to define and build a positive culture by aligning teams towards common objectives, creating transparency and accountability, and, structured goal setting.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Part 3: Methodology (to be published in next post)
&lt;/h3&gt;

&lt;h2&gt;
  
  
  Notable Quotes from the book
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;“Ideas are easy. Execution is everything.”&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Edwin Locke: &lt;em&gt;“hard goals” drive performance more effectively than easy goals. Second, specific hard goals “produce a higher level of output” than vaguely worded ones.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;A two-year Deloitte study found that no single factor has more impact than &lt;em&gt;“clearly defined goals that are written down and shared freely. . . . Goals create alignment, clarity, and job satisfaction.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Andy Grove &lt;em&gt;“Bad companies, are destroyed by crisis. Good companies survive them. Great companies are improved by them.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Leaders must get across the why as well as the what. Repeat until the entire team understands the &lt;em&gt;“why”&lt;/em&gt;. LinkedIn CEO Jeff Weiner *”&lt;em&gt;When you are tired of saying it, people are starting to hear it.”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Andy Grove &lt;em&gt;“For the feedback to be effective, it must be received very soon after the activity it is measuring occurs. Accordingly, an [OKR] system should set objectives for a relatively short period. For example, if we plan on a yearly basis, the corresponding [OKR] time should be at least as often as quarterly or perhaps even monthly.”&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Statutory Warning
&lt;/h2&gt;

&lt;p&gt;Focusing on goals solely leads to tunnel vision, infighting and possible unethical behavior. The book gives the example of &lt;a href="https://finance.yahoo.com/news/wells-fargo-scandals-the-complete-timeline-141213414.html"&gt;Wells Fargo&lt;/a&gt; where the number of new accounts opened was set as a goal.&lt;/p&gt;

&lt;h2&gt;
  
  
  My critiques of the book
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Too many feel good survivorship bias stories&lt;/li&gt;
&lt;li&gt;Some of the case studies and examples are outdated, for instances, Google no longer does 20% time for side projects&lt;/li&gt;
&lt;li&gt;Silicon Valley name dropping is rampant throughout the book&lt;/li&gt;
&lt;li&gt;No negative case studies featured. The book appears to make the supposition that either OKRs work or you’re not doing it right&lt;/li&gt;
&lt;li&gt;If committed OKRs take up most of your resources and aspirational OKRs which run multiple years are supposed to stretch your team, how is a team not supposed to burnout?&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>todayilearned</category>
      <category>business</category>
    </item>
    <item>
      <title>On remote work and time zones</title>
      <dc:creator>Santosh Hari</dc:creator>
      <pubDate>Mon, 24 Feb 2020 10:27:01 +0000</pubDate>
      <link>https://dev.to/santoshhari/on-remote-work-and-time-zones-2lc9</link>
      <guid>https://dev.to/santoshhari/on-remote-work-and-time-zones-2lc9</guid>
      <description>&lt;p&gt;Recently, I had the pleasure of working with a client on the opposite coast. However, this presented its own set of challenges, the primary one being dealing with time zones. So, I naturally learned to adjust my communication to factor in time zones since it would be embarrassing for me to schedule a 2pm call and then have the client not show up.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Protip: when working remotely always state timezone clearly. Heck, do this even when not remote&lt;br&gt;&lt;br&gt;
"Are you available at 2pm US Eastern today?"&lt;/p&gt;

&lt;p&gt;— Santosh Hari &lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EVAilbXS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f914.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EVAilbXS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/1f914.png" alt="🤔" width="72" height="72"&gt;&lt;/a&gt; (@_s_hari) &lt;a href="https://twitter.com/_s_hari/status/1229432822567522304?ref_src=twsrc%5Etfw"&gt;February 17, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I enable multiple time zones in Outlook, my chief timekeeper at work, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jYxEptik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2020/02/timezones.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jYxEptik--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2020/02/timezones.png" alt="timezones" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fwiw, you can also enable multiple timezones on Google Calendar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w1bK4pWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2020/02/timezones2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w1bK4pWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://santoshhari.files.wordpress.com/2020/02/timezones2.png" alt="timezones2" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the original tweet appeared to have sparked interest in the topic among my followers, largely techies and I received a lot of useful tips.&lt;/p&gt;

&lt;p&gt;David Haney uses relative time, which is great for same-day scheduling.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I also use relative time, as it applies the same way to everybody: "are you available in 90 minutes?"&lt;/p&gt;

&lt;p&gt;— David Haney (@haneytron) &lt;a href="https://twitter.com/haneytron/status/1229432916314394630?ref_src=twsrc%5Etfw"&gt;February 17, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Steve Lorello uses UTC, which works great when scheduling meeting with a software-focused crowd.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I usually use UTC when scheduling meetings with folks outside my time zone lol&lt;/p&gt;

&lt;p&gt;— Steve Lorello (&lt;a class="mentioned-user" href="https://dev.to/slorello"&gt;@slorello&lt;/a&gt;) &lt;a href="https://twitter.com/slorello/status/1229777386046214144?ref_src=twsrc%5Etfw"&gt;February 18, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Michael Godfrey uses the 24-hour calendar aka military time to avoid confusion.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have learned to do it all the time. Just to be safe. And to use 24 h time.&lt;/p&gt;

&lt;p&gt;— Michael Godfrey (@mgodfre3) &lt;a href="https://twitter.com/mgodfre3/status/1229591024214978565?ref_src=twsrc%5Etfw"&gt;February 18, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oscar “OZ” Zamora always specifies the location. This is something I could start doing myself since I communicate with Canadian coworkers all the time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;And location. Coworker from Mexico extended a teams meeting for today; holiday.&lt;/p&gt;

&lt;p&gt;— Oscar "OZ" Zamora (@ZamoraO) &lt;a href="https://twitter.com/ZamoraO/status/1229579618950242304?ref_src=twsrc%5Etfw"&gt;February 18, 2020&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A friend with a private Twitter account also mentioned blocking off time on the calendar if you don’t need to be disturbed. For instance, if you need to do heads-down coding all afternoon just block the afternoon off. Also, if you have coworkers or clients reaching you after-hours block those off on your calendar.&lt;/p&gt;

&lt;p&gt;Do you have any additional time zones and calendar tips? Feel free to share in the space below&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
