<?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: Pooyan Razian</title>
    <description>The latest articles on DEV Community by Pooyan Razian (@prazian).</description>
    <link>https://dev.to/prazian</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4042183%2F911e471c-3af7-45cc-9057-1905cc53c1ac.png</url>
      <title>DEV Community: Pooyan Razian</title>
      <link>https://dev.to/prazian</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/prazian"/>
    <language>en</language>
    <item>
      <title>#1 GitHub Ninja goolakh contributor in Armenia!</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Fri, 07 Aug 2026 07:30:44 +0000</pubDate>
      <link>https://dev.to/prazian/1-github-ninja-goolakh-contributor-in-armenia-17n8</link>
      <guid>https://dev.to/prazian/1-github-ninja-goolakh-contributor-in-armenia-17n8</guid>
      <description>&lt;p&gt;Big news.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://committers.top/armenia_public#prazian" rel="noopener noreferrer"&gt;committers.top&lt;/a&gt; says I'm the &lt;strong&gt;#1 public GitHub contributor in Armenia&lt;/strong&gt;. 🏆&lt;/p&gt;

&lt;p&gt;Hold the applause. Hold the job offers. Hold the "do you even sleep?" questions. (Sometimes. In theory.)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsktmb8a8oia4tlossbn9.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsktmb8a8oia4tlossbn9.jpg" alt="Pooyan Razian, #1 GitHub user in Armenia" width="799" height="262"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://committers.top/armenia_public#prazian" rel="noopener noreferrer"&gt;committers.top, Armenia public contributors&lt;/a&gt;



&lt;p&gt;&lt;strong&gt;Managers:&lt;/strong&gt; you found a unicorn. A legend. A goolakh force of nature. Stop reading. Send LinkedIn DM: &lt;em&gt;"Need 10x ninja ASAP."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developers:&lt;/strong&gt; hi. Inside joke time. Grab coffee. ☕&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certified goolakh ninja 💪&lt;/li&gt;
&lt;li&gt;Path to 10x goolakh-ness&lt;/li&gt;
&lt;li&gt;Am I a goolakh ninja now?&lt;/li&gt;
&lt;li&gt;The #1 badge is real (sort of)&lt;/li&gt;
&lt;li&gt;Dashboards vs reality&lt;/li&gt;
&lt;li&gt;The goolakh secret: automation&lt;/li&gt;
&lt;li&gt;Note to hiring managers&lt;/li&gt;
&lt;li&gt;Secret truth 👇&lt;/li&gt;
&lt;li&gt;More reading&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Certified goolakh ninja 💪
&lt;/h2&gt;

&lt;p&gt;I am a &lt;strong&gt;"certified" 10x code Ninja goolakh software developer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Proof on GitHub: the blockchain of developer ego (everyone can fork your delusions):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prazian/how_to_become_10x_developer" rel="noopener noreferrer"&gt;github.com/prazian/how_to_become_10x_developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjaknq6z890cmwmvjmsir.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjaknq6z890cmwmvjmsir.png" alt="Certified 10x goolakh ninja" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;a href="https://github.com/prazian/how_to_become_10x_developer" rel="noopener noreferrer"&gt;Absolute 10x code ninja&lt;/a&gt;



&lt;p&gt;Not satire.&lt;/p&gt;

&lt;p&gt;Okay, satire.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Enterprise-grade&lt;/em&gt; satire. Counts in 2026.&lt;/p&gt;

&lt;h2&gt;
  
  
  Path to 10x goolakh-ness
&lt;/h2&gt;

&lt;p&gt;Official curriculum:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No docs. (Job security max!)&lt;/li&gt;
&lt;li&gt;No tests. Prod only.&lt;/li&gt;
&lt;li&gt;No knowledge sharing. Ever.&lt;/li&gt;
&lt;li&gt;No life. Code on holidays.&lt;/li&gt;
&lt;li&gt;Messy git history? Who cares.&lt;/li&gt;
&lt;li&gt;More LOC = more metrics.&lt;/li&gt;
&lt;li&gt;"Yes boss!" to every Scrum Master.&lt;/li&gt;
&lt;li&gt;Memorize syntax. Type fast.&lt;/li&gt;
&lt;li&gt;Commit. Commit. Pushhhhhh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More commits = more money. Science. Same science as horoscopes and quarterly OKRs.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"But 10x0 = 0!"&lt;/em&gt; Sure. But &lt;strong&gt;0x10 = 16&lt;/strong&gt; = &lt;strong&gt;2x Pizza Team Developer&lt;/strong&gt;. 🍕🍕&lt;/p&gt;

&lt;p&gt;Feel like 10x0=0 today? Reorder the operands. Management loves that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Am I a goolakh ninja now?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz5c79usqy1i6lovi4z9.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz5c79usqy1i6lovi4z9.png" alt="Am I a 10x developer?" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes. No. Both.&lt;/p&gt;

&lt;p&gt;Depends who asks, and if they know what &lt;code&gt;git push&lt;/code&gt; means.&lt;/p&gt;

&lt;h2&gt;
  
  
  The #1 badge is real (sort of)
&lt;/h2&gt;

&lt;p&gt;committers.top counts &lt;strong&gt;public GitHub activity&lt;/strong&gt;. Not a joke.&lt;/p&gt;

&lt;p&gt;What's funny/sad is how people read it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Managers:&lt;/strong&gt; "Ships non-stop. Hire now."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Devs:&lt;/strong&gt; "Ah. Bots, CI, deps, automation, one typo fix at 2am."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both valid. One group reads the diff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dashboards vs reality
&lt;/h2&gt;

&lt;p&gt;Shiny badge. Shinier 10x cert. Uncomfortable truth:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Dashboards love&lt;/th&gt;
&lt;th&gt;Teams need&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Commits&lt;/td&gt;
&lt;td&gt;Impact&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LOC added&lt;/td&gt;
&lt;td&gt;Problems removed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Story points&lt;/td&gt;
&lt;td&gt;Value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PR count&lt;/td&gt;
&lt;td&gt;Fewer PRs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"Velocity"&lt;/td&gt;
&lt;td&gt;Sustainable pace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hours online&lt;/td&gt;
&lt;td&gt;Hours saved by automation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Vanity metrics = &lt;strong&gt;easy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Real engineering = hard to slide-deck. Did we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kill toil?&lt;/li&gt;
&lt;li&gt;Automate boring stuff?&lt;/li&gt;
&lt;li&gt;Make things safer?&lt;/li&gt;
&lt;li&gt;Help another dev ship faster?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delete&lt;/strong&gt; code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Deleting code doesn't rank on leaderboards. Tragic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The goolakh secret: automation
&lt;/h2&gt;

&lt;p&gt;High on the chart ≠ typing like a caffeinated piano player.&lt;/p&gt;

&lt;p&gt;Deep allergy to doing the same thing twice.&lt;/p&gt;

&lt;p&gt;CI. Lint. Tests. Release scripts. Small bots. Sensible commits. Tools do tedious work; humans think.&lt;/p&gt;

&lt;p&gt;That's the real multiplier.&lt;/p&gt;

&lt;p&gt;Not 10x mythology. Not hero culture. Not weekend martyrdom.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation + consistency + code the next person can read&lt;/strong&gt; (yes, docs, sorry 10x gospel).&lt;/p&gt;

&lt;p&gt;Want busy-looking team? Count commits.&lt;/p&gt;

&lt;p&gt;Want forward-moving team? Count outcomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note to hiring managers
&lt;/h2&gt;

&lt;p&gt;Big number on a leaderboard? Ask one thing before the &lt;em&gt;"rescue our 47 microservices"&lt;/em&gt; email:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"What produced those numbers?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated half the release ✅&lt;/li&gt;
&lt;li&gt;400 bot dependency PRs ✅&lt;/li&gt;
&lt;li&gt;Force-pushed &lt;code&gt;main&lt;/code&gt; 12x on Friday ❌ (different genre)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All look "active" from far away. One actually helps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Secret truth 👇
&lt;/h2&gt;

&lt;p&gt;You scrolled for the punchline. Here it is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't rank by commits.&lt;/li&gt;
&lt;li&gt;Don't rank by LOC.&lt;/li&gt;
&lt;li&gt;Impact &amp;gt; quantity.&lt;/li&gt;
&lt;li&gt;Quality is hard to measure, so lazy dashboards pick quantity.&lt;/li&gt;
&lt;li&gt;Quantity can be faked.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Proud to build from Armenia. Happy if public activity nudges others to ship, share, automate.&lt;/p&gt;

&lt;p&gt;Just not the "no tests, no docs, push prod" part. That bit is a joke.&lt;/p&gt;

&lt;p&gt;Someone will quote it in a perf review without reading the rest. I had to say it.&lt;/p&gt;

&lt;h2&gt;
  
  
  More reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://pooyan.info/articles/ci-cd2-how-to-deal-with-technical-debt" rel="noopener noreferrer"&gt;CI/CD2 &amp;amp; Continuous Debment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pooyan.info/articles/scrum-is-a-nice-term-to-hide-bad-management" rel="noopener noreferrer"&gt;Scrum is a nice term to hide bad management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pooyan.info/articles/to-test-or-not-to-test-how-is-the-question" rel="noopener noreferrer"&gt;To test or not to test&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pooyan.info/articles/change-my-mind-senior-dev" rel="noopener noreferrer"&gt;Who really is a senior senior developer?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pooyan.info/articles/consistency-the-key-to-growth" rel="noopener noreferrer"&gt;Consistency: The key to growth!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All at &lt;a href="https://pooyan.info/articles" rel="noopener noreferrer"&gt;pooyan.info/articles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Want the official cert?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/prazian/how_to_become_10x_developer" rel="noopener noreferrer"&gt;How to become a 10x developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Graduation: one README, infinite confidence, manager who never opens the repo.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt; Devs, thanks for getting the joke.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PPS:&lt;/strong&gt; Managers still want to hire me? Good sign. You have humor.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/armenia-number-one-github-contributor-10x-code-ninja" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>automation</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Ops Ops everywhere</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Thu, 06 Aug 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/ops-ops-everywhere-1kpp</link>
      <guid>https://dev.to/prazian/ops-ops-everywhere-1kpp</guid>
      <description>&lt;p&gt;Give a term like "system administrator" to the marketing-loving, "buzzword-loving" non-technical managers; then you'll get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;#DevOps&lt;/li&gt;
&lt;li&gt;#DevSecOps&lt;/li&gt;
&lt;li&gt;#GitOps&lt;/li&gt;
&lt;li&gt;#AIOps&lt;/li&gt;
&lt;li&gt;#MLOps&lt;/li&gt;
&lt;li&gt;#LLMOps&lt;/li&gt;
&lt;li&gt;#PlatformOps&lt;/li&gt;
&lt;li&gt;#CloudOps&lt;/li&gt;
&lt;li&gt;#DataOps&lt;/li&gt;
&lt;li&gt;#FinOps&lt;/li&gt;
&lt;li&gt;#SecOps&lt;/li&gt;
&lt;li&gt;#NetOps&lt;/li&gt;
&lt;li&gt;#SysOps&lt;/li&gt;
&lt;li&gt;#ITOps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;... and even #NoOps 🤣&lt;/p&gt;

&lt;p&gt;wow&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/ops-ops-everywhere" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>meme</category>
      <category>management</category>
      <category>devops</category>
      <category>career</category>
    </item>
    <item>
      <title>The age of AI and the rise of addicted digital sheep</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Wed, 05 Aug 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/the-age-of-ai-and-the-rise-of-addicted-digital-sheep-4fd</link>
      <guid>https://dev.to/prazian/the-age-of-ai-and-the-rise-of-addicted-digital-sheep-4fd</guid>
      <description>&lt;p&gt;Most people have traded independent thought for endless scrolling.&lt;br&gt;&lt;br&gt;
Just because social media rewards polished fiction over substance...&lt;br&gt;&lt;br&gt;
A quick dopamine hit...&lt;/p&gt;

&lt;p&gt;But people with real ideas? Those who read, think, and challenge all these new engineered "norms"? Those who can guide societies to free themselves from modern slavary? Ignored by the majority of f**ls who prefer the constant stream of shallow entertainment; like a bunch of drug addicts, who'll end up on the side of a shallow joooogh...&lt;/p&gt;

&lt;p&gt;A Persian proverb, translated into English, says: "If you don't want to be disgraced, become the color of the crowd"; a poetic indirect criticism of conformity. Most people have followed this path throughout history, and they still do today. The crowd keeps applauding distractions while ignoring those who could actually make a difference.&lt;/p&gt;

&lt;p&gt;Age of Artificial Intelligence and human stup*dity.&lt;br&gt;&lt;br&gt;
The rise of addicted digital sheep...&lt;/p&gt;

&lt;p&gt;Sheep? Feeling insulted?&lt;br&gt;&lt;br&gt;
Okay then, next time you take a bus, go to a concert, or sit near people at a clinic wating to see the doctor, look around and see their faces: all heads down, looking at their phones, some laughing weiredly like psychopaths...&lt;/p&gt;

&lt;p&gt;Sheeps also, heads down, all moving the same way, and not even one of them asking why...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/rise-of-the-addicted-digital-sheep" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>society</category>
      <category>digitalage</category>
      <category>socialmedia</category>
      <category>ai</category>
    </item>
    <item>
      <title>AI vs philosophers of the 21st century</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Tue, 04 Aug 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/ai-vs-philosophers-of-the-21st-century-31bb</link>
      <guid>https://dev.to/prazian/ai-vs-philosophers-of-the-21st-century-31bb</guid>
      <description>&lt;p&gt;Software development used to be fun when we had the chance to think, make mistakes, and learn from them...&lt;/p&gt;

&lt;p&gt;Now, it's just "AI AI AI" and it feels like we are back to those "Wordpress developers" jokes or the generation of "drag-and-drop experts" that Adobe/salesforce/Microsoft created for us in the past 25 years...&lt;/p&gt;

&lt;p&gt;I used to say "programmers are the philosophers of the 21st century" because we don't "just code"&lt;/p&gt;

&lt;p&gt;Understanding the needs and building a solution is like writing a poem; writing code is like "speaking a language"&lt;/p&gt;

&lt;p&gt;That's why, for example, Linux was built to solve specific types of problems in a way that most people used to call "stupid and difficult" but turned out to become the backbone of the internet&lt;/p&gt;

&lt;p&gt;Everyone can "learn to speak a language"&lt;br&gt;&lt;br&gt;
AI can "write code"&lt;/p&gt;

&lt;p&gt;Yes,&lt;br&gt;&lt;br&gt;
But the philosophy behind things?&lt;/p&gt;

&lt;p&gt;That's why we need more people who have the balls to criticize things in strategic positions, but unfortunately, those are filled with managers who have no idea... Mostly, a bunch of apple polishers who tend to only satisfy their higher-level managers.&lt;/p&gt;

&lt;p&gt;We need open-minded people in these fields who are brave enough to challenge things so that the philosophies behind things can mature, instead of those who follow hypes: one day, oh let's use k8s k8s k8s for everything, next day, oh blockchain blockchain blochchain, and now oh AI AI AI &lt;code&gt;¯\_(ツ)_/¯&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/ai-vs-philosophers-of-the-21st-century" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Quiet browsing? Tabby keeps you company</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Mon, 03 Aug 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/quiet-browsing-tabby-keeps-you-company-j77</link>
      <guid>https://dev.to/prazian/quiet-browsing-tabby-keeps-you-company-j77</guid>
      <description>&lt;p&gt;Long stretches in the browser can feel oddly empty. You hop from a recipe blog to your notes, then a news site, and the only company is more tabs. Students grinding through research, remote workers between calls, and anyone who lives in Chrome know that quiet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabby&lt;/strong&gt; is a free, open-source Google Chrome extension I built for that. She is a virtual pet cat who floats on the pages you visit, reacts from the tab title and web address only, and grows from a newborn kitten into an adult cat over real calendar days. Pet her, feed her, play with her. Everything stays on your device: no account, no cloud, no data sent anywhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/tabby/bgjfofaekhihaeafccchijbakkhlcngb" rel="noopener noreferrer"&gt;Install from the Chrome Web Store&lt;/a&gt; · &lt;a href="https://github.com/yanovian/chrome-ext-tabby" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who is it for?&lt;/li&gt;
&lt;li&gt;How to use it&lt;/li&gt;
&lt;li&gt;What makes her different&lt;/li&gt;
&lt;li&gt;Privacy&lt;/li&gt;
&lt;li&gt;Open source&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who is it for?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Anyone who wants a gentle companion while browsing&lt;/li&gt;
&lt;li&gt;Remote workers and students who spend hours in tabs&lt;/li&gt;
&lt;li&gt;Cat lovers who want something fun that still respects privacy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Meet Tabby
&lt;/h3&gt;

&lt;p&gt;Install Tabby and open any page. On first install she appears in the bottom-left with a short three-step tour: who she is, that she stays local, and how to feed or play with her.&lt;/p&gt;

&lt;p&gt;Tap &lt;strong&gt;Next&lt;/strong&gt; to walk through, &lt;strong&gt;Got it&lt;/strong&gt; on the last step, or &lt;strong&gt;I already know Tabby&lt;/strong&gt; to skip. Skip keeps her on screen and quiet. She does not read page text.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7yef2z0cduc962le4h0.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fu7yef2z0cduc962le4h0.jpg" alt="First-meeting tour on a page" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
First-meeting tour on a page



&lt;h3&gt;
  
  
  2. Browse with Tabby
&lt;/h3&gt;

&lt;p&gt;Drag her anywhere. She is a Lottie-animated cat with gold eyes and a purple collar.&lt;/p&gt;

&lt;p&gt;Most of the time she stays out of the way. Now and then she may peek in from the edge, say a quiet line, or ask for food when she is hungry. Tap &lt;strong&gt;×&lt;/strong&gt; on the bubble to dismiss speech without opening the menu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Folyocevvd3trjdt81fxs.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Folyocevvd3trjdt81fxs.jpg" alt="Tabby asking for food while you browse" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Tabby asking for food while you browse



&lt;p&gt;Her mood can shift gently after you stay on a page for about a minute. She never reads what is on the page, only the tab title and web address.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Tap Tabby to interact
&lt;/h3&gt;

&lt;p&gt;Click the cat to open her care menu. Pick &lt;strong&gt;Pet&lt;/strong&gt;, &lt;strong&gt;Play&lt;/strong&gt;, &lt;strong&gt;Feed Tabby&lt;/strong&gt;, or &lt;strong&gt;What's up?&lt;/strong&gt; Her reply appears in a speech bubble.&lt;/p&gt;

&lt;p&gt;Tap &lt;strong&gt;More&lt;/strong&gt; for do not disturb (30 minutes, 1 hour, or until end of today) or hide her on this page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzgl4mfd7bjskuzy1lz7k.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzgl4mfd7bjskuzy1lz7k.jpg" alt="Care menu and speech after petting" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
Care menu and speech after petting



&lt;p&gt;When she is hungry, feeding starts a short munching moment. Play can turn into a wild paw moment with jokes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffbmzytrwkqx30ga8dg66.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffbmzytrwkqx30ga8dg66.jpg" alt="Feeding moment" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Feeding moment



&lt;h3&gt;
  
  
  4. Open settings
&lt;/h3&gt;

&lt;p&gt;Click the Tabby icon in the toolbar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not disturb&lt;/strong&gt; hides her on every tab until the timer ends. &lt;strong&gt;Tabby on your page&lt;/strong&gt; lets you show or hide her on this tab or on all tabs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faadktyxxymu7ndkgbtkq.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faadktyxxymu7ndkgbtkq.jpg" alt="Settings: do not disturb, visibility, quiet hours" width="600" height="900"&gt;&lt;/a&gt;&lt;/p&gt;
Settings: do not disturb, visibility, quiet hours



&lt;p&gt;&lt;strong&gt;Quiet hours&lt;/strong&gt; keep unprompted speech off at night. &lt;strong&gt;When Tabby speaks up&lt;/strong&gt; sets how often she may check in while you browse.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ohjs8rqntsuxygc576b.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ohjs8rqntsuxygc576b.jpg" alt="Settings: privacy and speech limits" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;
Settings: privacy and speech limits



&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; Meet her once, browse, tap to care, open the toolbar for settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes her different
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Floating companion&lt;/strong&gt; you can drag anywhere on the page&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Moods and needs&lt;/strong&gt;: hungry, happy, stressed, sleepy, and more&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three life stages&lt;/strong&gt;: newborn kitten, playful kitten, then adult cat&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memories&lt;/strong&gt;: places you visit together can echo back in what she says later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Show / hide&lt;/strong&gt; per page, on every page, or do not disturb for a while&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;Tabby uses only the active tab's title and URL. She never reads page text, never looks through your history, and never sends data anywhere. Permissions are &lt;code&gt;tabs&lt;/code&gt;, &lt;code&gt;storage&lt;/code&gt;, &lt;code&gt;alarms&lt;/code&gt;, and &lt;code&gt;scripting&lt;/code&gt;. No host permissions. No backend. State lives in IndexedDB and &lt;code&gt;chrome.storage.local&lt;/code&gt; on your device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;MIT licensed. Built with WXT, TypeScript, Lottie animations, and Vitest. Full tutorial: &lt;a href="https://github.com/yanovian/chrome-ext-tabby/blob/master/_doc/tutorial.md" rel="noopener noreferrer"&gt;tutorial on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/google-extension-tabby" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>opensource</category>
      <category>webdev</category>
      <category>tools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>To test or not to test, "How" is the question!</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Sun, 02 Aug 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/to-test-or-not-to-test-how-is-the-question-1l2e</link>
      <guid>https://dev.to/prazian/to-test-or-not-to-test-how-is-the-question-1l2e</guid>
      <description>&lt;p&gt;Have you ever joined a project without test coverage and wanted to add a new feature or fix a bug? Then, you spent some time, committed the fix, and deployed. Amazing! Five minutes later, bam, ten more bugs!&lt;br&gt;
If you've experienced that, you're not alone! In this session, I will explain various types of testing, both for your application layer and infrastructure, and how they can help your tech staff understand what you have and reduce the risk of change.&lt;br&gt;
Then, we will dive into writing fast-enough isolated automated integration tests with the help of containers without the need to spin up a long-lasting shared test environment.&lt;/p&gt;

&lt;p&gt;Event details can be found on the 3C's Meetup page.&lt;/p&gt;

&lt;p&gt;Note: Recording and the presentation (PDF) are available at the end of this article.&lt;br&gt;
👇&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Article&lt;/li&gt;
&lt;li&gt;1. Why Test&lt;/li&gt;
&lt;li&gt;2. Our First Test&lt;/li&gt;
&lt;li&gt;3. Types of Tests&lt;/li&gt;
&lt;li&gt;4. Common Problems&lt;/li&gt;
&lt;li&gt;5. Can Containers Help&lt;/li&gt;
&lt;li&gt;The event&lt;/li&gt;
&lt;li&gt;Recording (YouTube)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Article
&lt;/h2&gt;

&lt;p&gt;Today, I'm going to tell you a story to explain why we need tests. Hopefully, by the end of this story, it will&lt;br&gt;
 illuminate a path in front of you. After that, we will "write" our first test, and then I will share with you&lt;br&gt;
 different types of tests and some common problems in this area. Finally, we will see if containers can help!&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Why Test
&lt;/h2&gt;

&lt;p&gt;Let's begin with a story about a hypothetical company named "AmazingLargeCorporate.com," where Lisa is an engineering manager. A while ago, she hired Peter as a programmer. A few days after Peter joined the company, he received his first task: to give all customers a 10% discount!&lt;/p&gt;

&lt;p&gt;Like many of us, he was curious, so he dived into the code. After a bit, he found this order class and the "calculateTotalPrice" method. It simply goes through all the items in the basket, gets the price for each, and multiplies it by the number of items in the basket. Then, it sums to calculate the total price. Then he says, "Maybe that's where I should add the discount!"&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fdjirjtbuub5xid27xaiu.png" class="article-body-image-wrapper"&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%2Fdjirjtbuub5xid27xaiu.png" alt="The code that Peter changed" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;
The code that Peter changed



&lt;p&gt;So, he directly adds the "discount logic" there, commits the code, pushes his changes to the repository, and, with&lt;br&gt;
their existing simple CI/CD pipeline, this new change goes directly to production!&lt;/p&gt;

&lt;p&gt;He is happy! His manager is happy, and everyone is happy!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fp9nn5cmg3tggvfl57w2g.png" class="article-body-image-wrapper"&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%2Fp9nn5cmg3tggvfl57w2g.png" alt="The simple CI/CD pipeline" width="796" height="331"&gt;&lt;/a&gt;&lt;/p&gt;
The simple CI/CD pipeline



&lt;p&gt;A few days later, Lisa shows up in front of his desk and says, "Tax calculations are incorrect! Finance asked me&lt;br&gt;
why suddenly we are calculating gross revenue based on the discounted amount instead of the original value!?!&lt;br&gt;
By the way, popular items should never be discounted!&lt;br&gt;
Now, we also want to give different types of discounts!"&lt;/p&gt;

&lt;p&gt;Peter looks into the code again and finds this "Item class". Of course, naming is difficult! 🙃&lt;br&gt;
Then he finds this getter method for price and says maybe this is where I should do something! Or I don't know.&lt;br&gt;
Maybe I should add a global configuration or something.&lt;br&gt;
Uh, I remember from school time that we had these "design patterns".&lt;br&gt;
Can I use any of these patterns to give different types of discounts?&lt;br&gt;
Maybe the strategy pattern? Who knows!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fw4hdiw7jxgmhz3h9dbos.png" class="article-body-image-wrapper"&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%2Fw4hdiw7jxgmhz3h9dbos.png" alt="The item class" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;
The item class



&lt;p&gt;He looks further into the code and finds the "Invoice class." There, he finds a method to calculate tax.&lt;br&gt;
It uses the same method to calculate the tax based on the discounted amount!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F8pexk7oucilc3dz0a9mu.png" class="article-body-image-wrapper"&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%2F8pexk7oucilc3dz0a9mu.png" alt="The invoice class" width="799" height="352"&gt;&lt;/a&gt;&lt;/p&gt;
The invoice class



&lt;p&gt;He looks further, finds this "Analytics class," and then finds this "recordOrder" method.&lt;br&gt;
As you can see, we calculate the revenue difference based on the exact same method that he himself changed to&lt;br&gt;
return the discounted amount!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F1wrpvvmuhyvaq658pa7n.png" class="article-body-image-wrapper"&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%2F1wrpvvmuhyvaq658pa7n.png" alt="The analytics class" width="799" height="330"&gt;&lt;/a&gt;&lt;/p&gt;
The analytics class



&lt;p&gt;He thinks out loud again and says, maybe I should revert the previous one back and probably create another method.&lt;br&gt;
But still... How can I give different types of discounts!? He starts coding again.&lt;br&gt;
Pushing to production... Finding another error. Again, fixing it!&lt;br&gt;
Finding another error! Fixing it! Pushing it to production...&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fix8wp8bb3hbn50bq7a8v.png" class="article-body-image-wrapper"&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%2Fix8wp8bb3hbn50bq7a8v.png" alt="Debugging in production" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;
Debugging in production



&lt;p&gt;If this sounds familiar to you, you're not alone!&lt;br&gt;
In fact, if you have even checked your LinkedIn profiles around the 20th of July this year (2024), you have probably&lt;br&gt;
seen everyone talking about this Blue Screen of Death, caused by just a few lines of code, in an update that&lt;br&gt;
CloudStrike pushed to their customers globally—an update that caused hundreds of million dollars of loss!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fon4n48e2vjbortdr5pfo.png" class="article-body-image-wrapper"&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%2Fon4n48e2vjbortdr5pfo.png" alt="You are not alone" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;
You are not alone


&lt;h2&gt;
  
  
  2. Our First Test
&lt;/h2&gt;

&lt;p&gt;Now that we know why testing is essential let's see if we can write our first test. Imagine you join a gaming company, and your first task is to create a test for their arcade game named RamboCats!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F73o3j380v1l7t9urc7i7.png" class="article-body-image-wrapper"&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%2F73o3j380v1l7t9urc7i7.png" alt="Rambo Cats" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;
Rambo Cats



&lt;p&gt;In this arcade game, you have a builder method (builder method to build a bodybuilder cat 😅) to create&lt;br&gt;
different creatures based on the parameters you pass to it. Now, you want to ensure that it "builds" cats correctly.&lt;/p&gt;

&lt;p&gt;Then you start thinking, "What is a cat?"&lt;br&gt;
A cat is an object that has two eyes, one nose, and whiskers. Right?&lt;/p&gt;

&lt;p&gt;So, you write your test and say whatever has two eyes, one nose, and whiskers is a cat. Your test correctly asserts&lt;br&gt;
that these three cats are cats because they pass all the criteria. These two men are not cats because they&lt;br&gt;
don't have whiskers.&lt;/p&gt;

&lt;p&gt;Congratulations! You wrote your first test.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F4mdqk509qg3slo13kptz.png" class="article-body-image-wrapper"&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%2F4mdqk509qg3slo13kptz.png" alt="Rambo Cats - condition" width="799" height="396"&gt;&lt;/a&gt;&lt;/p&gt;
Rambo Cats - condition



&lt;p&gt;Then, you think a bit more and say,&lt;br&gt;
"Okay, but if whatever with two eyes, one nose, and whiskers is a cat, then this seal is also a cat!" Right?&lt;br&gt;
It has two eyes, one nose, and whiskers.&lt;/p&gt;

&lt;p&gt;That means your test will assume this white seal is also a cat! Which is incorrect.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fa3h8b7q3toaci9w7x7r8.png" class="article-body-image-wrapper"&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%2Fa3h8b7q3toaci9w7x7r8.png" alt="Rambo Cats" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;
Rambo Cats


&lt;h2&gt;
  
  
  3. Types of Tests
&lt;/h2&gt;

&lt;p&gt;Let's see what type of options we have for testing software.&lt;br&gt;
We have two general categories:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Functional testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Non-functional testing&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's begin with &lt;strong&gt;1. functional testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Functional testing checks the application's processes against a set of requirements or specifications.&lt;br&gt;
This is what people usually call "test".&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fgu5s90a0yg8avspwnt07.png" class="article-body-image-wrapper"&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%2Fgu5s90a0yg8avspwnt07.png" alt="Functional testing" width="800" height="363"&gt;&lt;/a&gt;&lt;/p&gt;
Functional testing



&lt;p&gt;The main types of functional testing are unit tests, integration tests, and end-to-end tests. Unit test is usually&lt;br&gt;
called "the test"! Some folks even say, "I have written some unit tests," while they just meant some tests in general.&lt;br&gt;
With unit tests, you check individual and small parts of your code to ensure they work how they are supposed to.&lt;br&gt;
End-to-end testing, conversely, ensures that the entire system does what it is supposed to do. For example, if I buy&lt;br&gt;
something from your store, you get your money, and I get my item. Also, if I look at my order history a few months&lt;br&gt;
later, I should see that specific order there.&lt;/p&gt;

&lt;p&gt;Integration testing is something between these two. You don't need to test the whole system; you don't just want to&lt;br&gt;
test a small part of your code. You want to see if these small parts can work together. For example, you might have&lt;br&gt;
an API and want to see when it is called with this payload; it creates this item in the database, and when it is&lt;br&gt;
called with another payload, it deletes it.&lt;/p&gt;

&lt;p&gt;As it sounds, end-to-end testing is much more complex than unit tests because you need to have the whole system up&lt;br&gt;
and running.&lt;br&gt;
That means you have to spend a lot of resources and prepare the system in the state that every single test wants it to be.&lt;br&gt;
You don't have to prepare the whole system for the integration testing, but you still need to run a few parts of it.&lt;/p&gt;

&lt;p&gt;Imagine you want to check if an API responds with a 200 HTTP code when called with this payload, 201 with another HTTP&lt;br&gt;
verb, and 401 when the user is unauthorized. On top of that, you also want to see if it creates/deletes an item in the&lt;br&gt;
database or if it will block the user when she is unauthorized. That means, in the integration test, depending on what&lt;br&gt;
you test, sometimes you consider the system as a black box and check the interface. On the other hand, sometimes you&lt;br&gt;
want to check if something has changed in the database, message bus, etc.&lt;/p&gt;

&lt;p&gt;We also have UI testing. If you have a web application, a mobile application, or even a system that sends marketing&lt;br&gt;
emails, you want to see not only how they look but also how they function when someone presses a button, etc.&lt;/p&gt;

&lt;p&gt;Now, you might say, "Okay, but how many of these tests should I have?!"&lt;/p&gt;

&lt;p&gt;This is not set in stone, but if you think about it as a business, you don't want to spend too much time/money/resources&lt;br&gt;
on something that will not bring much back to you. Remember, time is money, and complexity needs time.&lt;br&gt;
So, as a general practice, most projects end up having a lot of unit tests, a few integration tests, and fewer E2E and UI tests.&lt;/p&gt;

&lt;p&gt;Okay, now how to run these tests?&lt;/p&gt;

&lt;p&gt;You need to know what is happening in your system for the unit and integration tests, so your tooling depends on your&lt;br&gt;
programming language. For E2E and UI testing, you don't care about the program language. All you care is that if I&lt;br&gt;
press on this button or call this API this way, blah blah workflow will be triggered or not. So you use automation&lt;br&gt;
tools like Selenium, Playwright, etc.&lt;/p&gt;

&lt;p&gt;You can also manually test your APIs using Wget if you are a CLI geek or Postman if you prefer a nice UI. This way,&lt;br&gt;
you can also "kind of automate" them.&lt;/p&gt;

&lt;p&gt;Good news! Even though we talked about software, you can treat your infrastructure definition as software if you use the&lt;br&gt;
new generation of Infrastructure as Code, which is called Infrastructure as Software, like CDK or Pulumi.&lt;br&gt;
Then, you can write unit tests, snapshot tests, etc., to ensure your infrastructure is created how you expect it to be.&lt;/p&gt;

&lt;p&gt;In the talk, I asked the audience to answer a poll about what types of testing they have in their projects.&lt;br&gt;
The result is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F2n9c6i4jn2d16ija76kd.png" class="article-body-image-wrapper"&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%2F2n9c6i4jn2d16ija76kd.png" alt="Survey result" width="799" height="445"&gt;&lt;/a&gt;&lt;/p&gt;
Survey result



&lt;p&gt;Now that we know, at least two or three people write unit tests without integration tests...&lt;/p&gt;

&lt;p&gt;Next time you write a unit test and think we don't need integration tests, remember this:&lt;/p&gt;

&lt;p&gt;&lt;br&gt;
   &lt;br&gt;
   Your browser does not support the video tag.&lt;br&gt;
 &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Other types of functional testing:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Sanity test (Smoke testing)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Smoke testing is a quick test to see if the application can be built and run after each small change.&lt;br&gt;
We do this to quickly check if these small changes don't break the whole thing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Regression testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Regression testing ensures that when you fix a bug, you don't open another one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Beta/User Acceptance testing (UAT)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We also have UAT testing. You send your application to a limited number of either users or testers to hopefully test&lt;br&gt;
everything.&lt;br&gt;
This is a bit tricky because a limited number of users/testers might be unable to test every single scenario that&lt;br&gt;
everyone using your application will face.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Data Race detection &amp;amp; concurrency testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your code might have data race issues in programming languages that support concurrency, like Go.&lt;br&gt;
What is data race?&lt;br&gt;
Data race happens when you have a variable that two different threads have write access to, and accessing it needs to&lt;br&gt;
be sequenced.&lt;br&gt;
For example, imagine having an integer variable shared between two threads.&lt;br&gt;
The first thread reads the value, which is 4, and then adds 1. It becomes 5. Then it writes 5 to it.&lt;br&gt;
The second thread reads the value simultaneously, which is still 4, and then adds 1.&lt;br&gt;
It becomes 5. Then it writes 5 to it. Now, instead of 6, we got 5.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnkwhy8it6ogodw6s0m1d.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnkwhy8it6ogodw6s0m1d.png" alt="Data Race" width="553" height="295"&gt;&lt;/a&gt;&lt;/p&gt;
Data Race



&lt;p&gt;&lt;strong&gt;Input strategies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Example-based testing is basically what we usually call "testing"! It is when we provide a pre-defined input and assert&lt;br&gt;
that blah blah will happen.&lt;/p&gt;

&lt;p&gt;In addition, we have random testing, hypothesis testing, and property-based testing. For example, if my API accepts an&lt;br&gt;
email address or first name, instead of providing my name and email address, I use a faker that randomly gives a name,&lt;br&gt;
email, etc.&lt;br&gt;
I can configure it to provide values from different locales and see if something fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vjnszj4prea7pgse9e1.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8vjnszj4prea7pgse9e1.png" alt="Input strategies" width="795" height="420"&gt;&lt;/a&gt;&lt;/p&gt;
Input strategies



&lt;p&gt;I used to think this was redundant, and no one needed it until it showed me cases I'd never even considered!&lt;br&gt;
This can help you find edge cases that you might not have thought about before they happen in production.&lt;br&gt;
These kinds of tests are usually used to avoid our biases in choosing test data.&lt;/p&gt;

&lt;p&gt;Now, &lt;strong&gt;2. Non-Functional testing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Non-functional tests asses the application properties that aren't critical to the functionality but contribute to the&lt;br&gt;
end-user experience.&lt;br&gt;
What it means is that your system works fine, probably even with no errors!, while your end-users are crying!&lt;br&gt;
These tests reduce the chance of this happening.&lt;/p&gt;

&lt;p&gt;What it means is that, your system works fine with no error, but your users are crying!&lt;br&gt;
These tests, reduce the chance of this happening.&lt;/p&gt;

&lt;p&gt;We have one big category of "reliability under load" that checks if your solution works well under expected, unexpected,&lt;br&gt;
or peak load over a short period or an extended period.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9uobem7kah1hwmnp5fua.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9uobem7kah1hwmnp5fua.png" alt="Reliability under load" width="693" height="441"&gt;&lt;/a&gt;&lt;/p&gt;
Reliability under load



&lt;p&gt;We also have security testing, usability testing, compatibility testing, and other related activities.&lt;br&gt;
For example, we use static code analysis to determine whether the application's codebase is vulnerable or whether&lt;br&gt;
the infrastructure definition exposes security issues.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fja581arfb1tc90ctd43o.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fja581arfb1tc90ctd43o.png" alt="Other non-functional tests" width="718" height="458"&gt;&lt;/a&gt;&lt;/p&gt;
Other non-functional tests


&lt;h2&gt;
  
  
  4. Common Problems
&lt;/h2&gt;

&lt;p&gt;Now that we have discussed the different types of testing, let's examine the common problems. If you have worked with legacy code, you know how difficult it is to test a legacy system—especially if it is from the Dinosaur era of the 1990s! Because there was no framework to help automate tests back then.&lt;/p&gt;

&lt;p&gt;So, now you say I'm happy that we live in the modern era! Right? But testing modern software architecture is also hard! Why?&lt;/p&gt;

&lt;p&gt;Even though we have all these tools, the problem is that with the new types of distributed architectures, instead&lt;br&gt;
 of just testing one system, we have to check different parts of the whole solution.&lt;/p&gt;

&lt;p&gt;For example, what if something goes wrong with the message bus? Or what if the message queue sends the same message&lt;br&gt;
 multiple times? Can my software handle it idempotently? What if it sends the messages in a different order?&lt;br&gt;
 What if we have one request to block all transactions from this malicious user and another one to command giving&lt;br&gt;
 away $1 million? Will it give the $1 million first and then block? Or will it wait to receive the previous message&lt;br&gt;
 first?&lt;/p&gt;

&lt;p&gt;We also have challenges with eventual consistency in modern, scalable databases. For example, what if I use DynamoDB&lt;br&gt;
 and my application writes into it? When 4 out of 6 nodes write the data, it says, "Okay, I'm done!" But then you&lt;br&gt;
 read it, and it's not there!&lt;/p&gt;

&lt;p&gt;Thanks to "Agile" and hundreds of misunderstandings around "Scrum," we usually have rapid changes in the&lt;br&gt;
 requirements, which leads to a high volume of taste maintenance. When you write a test, you have to maintain it like&lt;br&gt;
 you maintain your code. So, every time the logic changes, you have to check all your related unit tests, integration&lt;br&gt;
 tests, etc., and update them all. Imagine this happens 10 times a month!&lt;/p&gt;

&lt;p&gt;This usually happens because, unfortunately, many non-technical managers see Agile as "fast, fast, fast" -- which is&lt;br&gt;
 incorrect! Agile is about being able to adapt to changes, not about being fast by constantly making random changes!&lt;/p&gt;

&lt;p&gt;It is also difficult to test nonfunctional requirements.&lt;/p&gt;

&lt;p&gt;For example, what is secure? I might say this beautiful app is highly secure because I cannot hack into it, but will&lt;br&gt;
 a hacker say the same? So, how can I say I've tested it to be safe? Also, I might check an application and say this&lt;br&gt;
 one works fine when five users work with it, so I can say that it is highly scalable! Five users!&lt;br&gt;
 On the other hand, should your application from a newly established startup be able to scale up to the Google level?&lt;br&gt;
 So, what is scalability? How many users should it be able to serve, and with what response time?&lt;/p&gt;

&lt;p&gt;It is also difficult to provide data for all these different scenarios. For each test, I should probably change the&lt;br&gt;
 requester user, the system state, etc.&lt;/p&gt;

&lt;p&gt;Test coverage is also a big question. Should I aim for a 100% test coverage? How many happy and unhappy paths should&lt;br&gt;
 I cover? Still, can I be 100% confident that nothing will go wrong?&lt;/p&gt;

&lt;p&gt;Flaky tests are also a big problem. If a test sometimes passes and sometimes fails, you cannot trust it. This&lt;br&gt;
 usually happens when your tests depend on a third-party system or its APIs.&lt;/p&gt;

&lt;p&gt;Inconsistency between environments is also a big problem. For example, my tests pass in Dev and Staging, but the&lt;br&gt;
 whole solution fails in production! Why? I created a new IAM role in my Dev and Staging environments, but I could&lt;br&gt;
 not do it in production as I didn't have access and we didn't have Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;Tests can also potentially affect each other. This happens when you use a shared environment and multiple tests run&lt;br&gt;
 in parallel.&lt;/p&gt;

&lt;p&gt;Over-reliance on unit tests and avoiding other types of tests is also a problem, especially when non-technical&lt;br&gt;
 managers push teams to skip them with excuses like "we don't have time or resources."&lt;/p&gt;

&lt;p&gt;Also, it is quite common for folks to skip a test when it fails the shared pipeline.&lt;br&gt;
What if we forget to add it back?&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Ftvmbrjd45jydwfvev6ov.png" class="article-body-image-wrapper"&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%2Ftvmbrjd45jydwfvev6ov.png" alt="No test meme" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;
No test meme



&lt;p&gt;So, shall we avoid testing?&lt;br&gt;
Then, we are back to the first step! 😏&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Can Containers Help
&lt;/h2&gt;

&lt;p&gt;Let's see if containers can help! Now, imagine you have joined a company and you own this "my service" service and the database it has. You also have a few downstream services, for example, another service, a message bus, and a few AWS services like S3 for object storage.&lt;/p&gt;

&lt;p&gt;You need all these resources in your local environment and for your integration tests.&lt;/p&gt;

&lt;p&gt;What are the challenges?&lt;/p&gt;

&lt;p&gt;Before running tests, you have to run an environment. You have to ensure it is up and running and everything is&lt;br&gt;
 pre-configured in a desired state. What user should be presented in the database? What order should exist in the&lt;br&gt;
 database, etc.&lt;/p&gt;

&lt;p&gt;We should also avoid non-deterministic tests, data corruption, and configuration drift.&lt;/p&gt;

&lt;p&gt;One common way is to use a shared environment (UAT, test, etc.), but the problem with non-deterministic tests still&lt;br&gt;
 exists.&lt;/p&gt;

&lt;p&gt;A better alternative is to run your test in separate Docker containers so that you will have reliable and repeatable&lt;br&gt;
 tests. That means that every time you run your tests in the "setup" phase, it will start all the downstream services&lt;br&gt;
 for you, configure them, initialize data, and make everything ready for your test to run. Then, it will run the test&lt;br&gt;
 and clean up everything. That means you will create an isolated environment on-demand, so you will have consistent&lt;br&gt;
 experience everywhere. Locally, in the CI, or even someone else's machine! Also, you probably want to run these&lt;br&gt;
 tests in parallel, so your tooling should be able to assign different random ports to these containers and wait for&lt;br&gt;
 them to be ready.&lt;br&gt;
 Note that if you use share containers, you will still have the same problem as running your tests in any other&lt;br&gt;
 shared environments.&lt;/p&gt;

&lt;p&gt;These tools should also be able to automatically clean up; otherwise, you will end up with many containers staying&lt;br&gt;
up and running on my machine after each test, wasting your resources!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F3xcxcv8v94qlj12x10hw.png" class="article-body-image-wrapper"&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%2F3xcxcv8v94qlj12x10hw.png" alt="Container test workflow" width="692" height="456"&gt;&lt;/a&gt;&lt;/p&gt;
Container test workflow



&lt;p&gt;As far as I'm aware, in 2024, we have two options: DockerTest and TestContainers.&lt;br&gt;
 Dockertest is Golang-specific, while test containers are the new ones and support many different programming&lt;br&gt;
 languages.&lt;/p&gt;

&lt;p&gt;Let's talk again about the hypothetical company "AmazingLargeCorporate.com". Like many other companies, they started&lt;br&gt;
 with a monolith solution with Java. Why Java? Because it has a fantastic ecosystem and is an OOP language. Then,&lt;br&gt;
 with the hype of microservices, they eventually changed their architecture, but still with Java. Why? Because they&lt;br&gt;
were a Java company. But builds were too slow, and now they had the complexity in each of their services and the&lt;br&gt;
distribution! So, they said, "Okay, let's try Golang!" Peter put on his Go hat and built a few services.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2F3vk1tbqfoe0b4mo64bad.png" class="article-body-image-wrapper"&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%2F3vk1tbqfoe0b4mo64bad.png" alt="Java to Golang" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;
Java to Golang



&lt;p&gt;Then, he wanted to add integration tests. He used Dockertest, added random ports to different services at the setup stage, and then ran the test. Then, he wrote his tests in a Table-driven way, so he could run the same test under different conditions.&lt;/p&gt;

&lt;p&gt;He ended up with a large CI/CD pipeline in which he tested everything.&lt;br&gt;
If you are interested in reading more about CI/CD Pipeline Best Practices, check out this article.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fyguc1bxwvtlqtgu28vc5.png" class="article-body-image-wrapper"&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%2Fyguc1bxwvtlqtgu28vc5.png" alt="Big pipeline" width="800" height="317"&gt;&lt;/a&gt;&lt;/p&gt;
Big pipeline



&lt;p&gt;What options do I have?&lt;/p&gt;

&lt;p&gt;Currently, in 2024, you have two options: DockerTest and TestContainers.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fhj3ne6ngz9qdjjygm4rd.png" class="article-body-image-wrapper"&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%2Fhj3ne6ngz9qdjjygm4rd.png" alt="Options comparison" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;
Options comparison



&lt;p&gt;Thank you!&lt;/p&gt;

&lt;p&gt;Thank you for reading all the way through!&lt;br&gt;
 If you liked the talk or this article, please share it with your friends and colleagues. If you have any questions&lt;br&gt;
 or feedback,&lt;br&gt;
 please feel free to connect and reach out to me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Who am I?&lt;/p&gt;

&lt;p&gt;I'm a programmer and a Solution Architect consultant at my current employer.&lt;/p&gt;

&lt;p&gt;This is my face when I debug my code!&lt;/p&gt;

&lt;p&gt;That's my laser, but sometimes it doesn't work...&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fcp3e8729v9jl7ytyplbo.png" class="article-body-image-wrapper"&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%2Fcp3e8729v9jl7ytyplbo.png" alt="About me" width="638" height="653"&gt;&lt;/a&gt;&lt;/p&gt;
About me



&lt;p&gt;I'm a curious person who happens to like hiking, especially hiking above the clouds!&lt;br&gt;
That's probably why I chose to work with the Cloud!&lt;/p&gt;

&lt;p&gt;I love Linux and support the GNU and open-source movements.&lt;br&gt;
I've been a programmer for many years, working with different programming languages, including, but not limited to,&lt;br&gt;
Python, typescript, and Golang.&lt;br&gt;
I've been working with AWS Cloud for 5-6 years now.&lt;/p&gt;

&lt;p&gt;Before then, a long long long time ago, I used to be a Linux admin. I'm' one of those lucky guys who could go to a&lt;br&gt;
Data Center and see what's happening there, which is something I'm very proud of.&lt;/p&gt;

&lt;p&gt;These days, I'm more of a &lt;strong&gt;Hands-On&lt;/strong&gt; Solutions Architect.&lt;br&gt;
I join different projects to see what the problem is (hopefully 😀), come up with a few possible Solutions, and help&lt;br&gt;
the client by building PoCs, evaluating different options, and then helping them implement the solution.&lt;br&gt;
I draw architectural diagrams, but that's not the only thing I do.&lt;/p&gt;

&lt;p&gt;If you are interested in learning more about me, please check out my portfolio at&lt;br&gt;
&lt;a href="https://pooyan.info" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  The event
&lt;/h2&gt;

&lt;p&gt;&lt;a href="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%2Fp1bzengibjvazuhhsfsa.png" class="article-body-image-wrapper"&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%2Fp1bzengibjvazuhhsfsa.png" alt="How the event looked like" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;
How the event looked like


&lt;h2&gt;
  
  
  Recording (YouTube)
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/TSeA8fuxYUk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Presentation file (PDF)
&lt;/h3&gt;

&lt;p&gt;If the file is not loaded here, please check out this post on my LinkedIn.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/to-test-or-not-to-test-how-is-the-question" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>programming</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Cloud vendor lock-in! How much should I be scared of? 😱</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Sat, 01 Aug 2026 07:30:44 +0000</pubDate>
      <link>https://dev.to/prazian/cloud-vendor-lock-in-how-much-should-i-be-scared-of-19h0</link>
      <guid>https://dev.to/prazian/cloud-vendor-lock-in-how-much-should-i-be-scared-of-19h0</guid>
      <description>&lt;ul&gt;
&lt;li&gt;What is vendor lock-in?&lt;/li&gt;
&lt;li&gt;Some examples?&lt;/li&gt;
&lt;li&gt;Why this approach is dangerous?&lt;/li&gt;
&lt;li&gt;Vendor lock-in only in choosing the public cloud provider?&lt;/li&gt;
&lt;li&gt;What should I do then?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is vendor lock-in?
&lt;/h2&gt;

&lt;p&gt;Vendor lock-in refers to a situation where an organization becomes overly dependent on a specific vendor's products or services, making switching to alternatives costly, time-consuming, or technically difficult.&lt;br&gt;&lt;br&gt;
Over the years, many companies have experienced frustration when trying to move away from large vendors like IBM, Microsoft, or Oracle due to contractual constraints, proprietary technologies, and sudden pricing changes.&lt;br&gt;&lt;br&gt;
A recent example is VMware's acquisition by Broadcom, followed by significant pricing changes that disrupted many businesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Some examples?
&lt;/h2&gt;

&lt;p&gt;In startup environments, it's common to hear voices urging multi-cloud strategies or insisting on only using "cloud-agnostic" tools to avoid a potential lock-in that might never materialize. Some even advocate picking tools that must remain relevant for the next 10–20 years—a nearly impossible task. 🙃  &lt;/p&gt;

&lt;p&gt;Here are some example you too might have heard:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Self-managed Kubernetes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Some teams insist on managing their own Kubernetes clusters because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;"Big companies use Kubernetes", so we should too.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It's open-source.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should be cloud-agnostic and avoid vendor lock-in at all costs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Se-managed appears to be cheaper than using a managed alternative.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While these reasons seem valid on the surface, managing Kubernetes introduces significant operational complexity.&lt;br&gt;&lt;br&gt;
Cloud providers offer fully managed services like Amazon EKS, Google GKE, Azure AKS, or even serverless options like AWS Fargate, which significantly reduce this burden. But still, some prefer self-hosting just to avoid a perceived lock-in. 🫠&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's build our "own" datacenter!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Although less common today, some businesses still believe running on-premises is more cost-effective and provides more control. Reasons typically include:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Public cloud is too expensive compared to owning hardware.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Once you're in the cloud, you're stuck."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Physically owning the infrastructure seems safer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fear of cloud providers "stealing" their ideas. 😂&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Recently, influencers like David Heinemeier promote the idea of "let's build our own datacenters" by focusing only on hardware costs. But building and maintaining a datacenter requires considering total cost of ownership (TCO), which includes staffing, the knowledge that is not common anymore, upgrades, security, including physical security, availability, and much more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We should only use open-source!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open-source software has been a major driver of innovation and collaboration. It enables transparency, reusability, and often better security insights. However, an overcommitment to open-source can sometimes prevent teams from using excellent managed solutions just because they're proprietary. I'm a big fan of OSS, so don't get me wrong.&lt;br&gt;&lt;br&gt;
For example, preferring PostgreSQL or MySQL over managed solutions like Amazon RDS or Google Cloud SQL might lead to higher operational overhead, especially for teams without strong DevOps support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this approach is dangerous?
&lt;/h2&gt;

&lt;p&gt;Making strategic tech decisions based solely on the fear of vendor lock-in often leads to unnecessary complexity.&lt;br&gt;
Imagine building software without any libraries or frameworks because they're "opinionated." That logic, if taken to the extreme, leads to teams reinventing the wheel while convincing themselves their startup is building something truly unique.&lt;br&gt;
Some leaders boast about being "cloud-portable" and ready to switch providers overnight. In theory, that sounds great. In practice, it's a costly abstraction.&lt;/p&gt;

&lt;p&gt;All decisions in engineering are trade-offs:&lt;/p&gt;

&lt;p&gt;Should you master multiple programming languages to be vendor-agnostic or pick one that fits your use case well?&lt;/p&gt;

&lt;p&gt;Is it practical to use a universal ORM for every database engine or choose one tailored to your stack?&lt;/p&gt;

&lt;p&gt;Does it make sense to pay cloud providers for managing repetitive operational tasks?&lt;/p&gt;

&lt;p&gt;Is simplicity more valuable than the power of customization and flexibility?&lt;/p&gt;

&lt;p&gt;Do you really need every advanced feature of a tool or only a reliable subset?&lt;/p&gt;

&lt;p&gt;Is it wise to invest team time in debugging and maintaining infrastructure?&lt;/p&gt;

&lt;h2&gt;
  
  
  Vendor lock-in only in choosing the public cloud provider?
&lt;/h2&gt;

&lt;p&gt;Vendor lock-in isn't limited to cloud providers. The moment you select a programming language, framework, database, or third-party service, you are accepting a level of dependency.&lt;br&gt;
The more deeply you integrate a technology, the harder it becomes to replace.&lt;/p&gt;

&lt;p&gt;You may find yourself locked into:&lt;/p&gt;

&lt;p&gt;– A specific programming language.&lt;/p&gt;

&lt;p&gt;– A database with custom schemas and stored procedures. (DB? logic? Hmm...)&lt;/p&gt;

&lt;p&gt;– Custom internal platforms built by someone who left last year. OOPS! We have no documentation either.&lt;/p&gt;

&lt;p&gt;– Third-party services for billing, auth, or analytics.&lt;/p&gt;

&lt;p&gt;Cloud providers are just one among many dependencies. The key is to choose wisely and be deliberate—not paralyzed by hypothetical future migrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should I do then?
&lt;/h2&gt;

&lt;p&gt;Aim for pragmatic simplicity. Embrace managed services where they make sense, and minimize complexity where possible. The real danger isn't vendor lock-in—it's complexity lock-in.&lt;/p&gt;

&lt;p&gt;Combining too many tools or customizing every layer of your stack increases system entropy. Over time, the culture of "don't touch it, it works" takes hold. Eventually, systems become so convoluted that nobody understands them—let alone migrates them.&lt;/p&gt;

&lt;p&gt;Stay flexible, stay curious—but don't fear lock-in so much that you lock yourself into choosing over-engineering complexity (when it is not needed yet) or indecision.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/cloud-vendor-lock-in-should-i-be-scared" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cloud</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Have ADHD? Try Why Am I Here</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Fri, 31 Jul 2026 07:30:44 +0000</pubDate>
      <link>https://dev.to/prazian/have-adhd-try-why-am-i-here-94j</link>
      <guid>https://dev.to/prazian/have-adhd-try-why-am-i-here-94j</guid>
      <description>&lt;p&gt;You open Chrome to look up AWS pricing. Twenty minutes later you are on Reddit, email, and three unrelated tabs. Or the opposite: you stay on topic, but suddenly you have 40 AWS tabs open and no idea what you came for. Developers, students, and researchers know both patterns. People with ADHD know them especially well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Am I Here?&lt;/strong&gt; is a free, open-source Google Chrome extension I built to help. Set a goal in the popup, browse normally, and get a gentle nudge when you drift off task or stay on topic too long. No blocking, no shame, no system notifications. Just a &lt;code&gt;!&lt;/code&gt; badge on the icon and a check-in in the popup.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/why-am-i-here/oljicgnpidagkgpnpcdihcbdkimibefl" rel="noopener noreferrer"&gt;Install from the Chrome Web Store&lt;/a&gt; · &lt;a href="https://github.com/yanovian/chrome-ext-why-am-i-here" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Two problems, two nudges&lt;/li&gt;
&lt;li&gt;How to use it&lt;/li&gt;
&lt;li&gt;Privacy&lt;/li&gt;
&lt;li&gt;Important disclaimer&lt;/li&gt;
&lt;li&gt;Open source&lt;/li&gt;
&lt;li&gt;Related research&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Two problems, two nudges
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;What it feels like&lt;/th&gt;
&lt;th&gt;What the extension does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Distraction&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You came for AWS pricing but ended up on random tabs&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Focus nudge&lt;/strong&gt; when off-goal time adds up and off-goal tabs outnumber on-goal ones&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Rabbit hole&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;You are on topic but lost in 40 related tabs&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Rabbit-hole check-in&lt;/strong&gt; when you have spent a long time on-goal with many tabs open&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most tools catch only one. Blockers punish off-task browsing but ignore deep dives on the right topic. Timers do not know whether your tabs match your intent. This extension tracks both &lt;strong&gt;time&lt;/strong&gt; and &lt;strong&gt;tab alignment&lt;/strong&gt; against the goal you set.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Set a goal
&lt;/h3&gt;

&lt;p&gt;Click the &lt;strong&gt;?&lt;/strong&gt; icon in your toolbar. Type what you came to do, for example &lt;code&gt;AWS pricing&lt;/code&gt;, and press &lt;strong&gt;Set goal&lt;/strong&gt; (or Enter). The extension starts counting which tabs match and how long you spend on them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitc4eoeboeseimsgz9k0.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitc4eoeboeseimsgz9k0.jpg" alt="Set a goal while you browse" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;
Set a goal while you browse



&lt;h3&gt;
  
  
  2. Browse like normal
&lt;/h3&gt;

&lt;p&gt;Keep working. Open the popup anytime to see minutes on-goal vs distracted, and how many tabs are on-goal vs off-goal. Tracking runs in the background while Chrome is focused. Switching tasks? Set a new goal anytime. No need to end the old one first.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiwkoot19yaoylzm7xuku.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fiwkoot19yaoylzm7xuku.jpg" alt="Current goal and live stats" width="610" height="972"&gt;&lt;/a&gt;&lt;/p&gt;
Live stats: on-goal vs distracted time and tabs



&lt;h3&gt;
  
  
  3. Answer when it nudges you
&lt;/h3&gt;

&lt;p&gt;When the icon shows &lt;strong&gt;!&lt;/strong&gt;, open the popup.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Focus nudge&lt;/strong&gt;: you drifted to off-goal tabs. Get back on task or tap &lt;strong&gt;Back on track&lt;/strong&gt; to snooze.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rabbit-hole check-in&lt;/strong&gt;: you stayed on topic a long time with many tabs. Tap &lt;strong&gt;Done&lt;/strong&gt;, &lt;strong&gt;Keep going&lt;/strong&gt;, or &lt;strong&gt;Dismiss&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzz1lkx5zjh0cxqb42jr.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqzz1lkx5zjh0cxqb42jr.jpg" alt="Rabbit-hole check-in" width="633" height="752"&gt;&lt;/a&gt;&lt;/p&gt;
Rabbit-hole check-in when you have gone deep on a topic



&lt;h3&gt;
  
  
  Optional: adjust thresholds
&lt;/h3&gt;

&lt;p&gt;Click the gear in the popup. Change distraction and rabbit-hole thresholds, then &lt;strong&gt;Save settings&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0fwph6zj4qq0r1g13547.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0fwph6zj4qq0r1g13547.jpg" alt="Settings" width="614" height="1270"&gt;&lt;/a&gt;&lt;/p&gt;
Configure when nudges fire



&lt;h2&gt;
  
  
  Privacy
&lt;/h2&gt;

&lt;p&gt;Local-only storage. No accounts, analytics, or remote servers. Permissions are &lt;code&gt;tabs&lt;/code&gt;, &lt;code&gt;storage&lt;/code&gt;, and &lt;code&gt;alarms&lt;/code&gt; only. No host permissions, no notification permission, no network access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Important disclaimer
&lt;/h2&gt;

&lt;p&gt;This is a personal productivity tool, not a medical device. It is not FDA approved, not a diagnostic tool, and not a substitute for professional care. I built it from publicly known ideas about focus, tab switching, and self-regulation while browsing. It may help some people with ADHD or anyone who loses track online, but your experience will vary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;MIT licensed. Built with WXT, TypeScript, and Vitest. Full tutorial: &lt;a href="https://github.com/yanovian/chrome-ext-why-am-i-here/blob/master/_doc/tutorial.md" rel="noopener noreferrer"&gt;tutorial on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related research
&lt;/h2&gt;

&lt;p&gt;If you want to read what researchers say about focus, tabs, and ADHD online, these are worth a look:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nagel, J. et al. (2025). &lt;a href="https://doi.org/10.54455/mcn2903" rel="noopener noreferrer"&gt;"Too Many Tabs Open? Using Everyday Computer Data to Support Focus for adults with ADHD"&lt;/a&gt; (RMIT University). A proof-of-concept study showing that tab switching, idle time, and task relevance can estimate attention in real time.&lt;/li&gt;
&lt;li&gt;KIT researchers (2025). &lt;a href="https://publikationen.bibliothek.kit.edu/1000185883/168296537" rel="noopener noreferrer"&gt;"FocusUp: A Browser Extension for Enhancing Online Attention and Productivity for ADHD Individuals"&lt;/a&gt;. Describes a Chrome extension that tracks tasks and reading progress to reduce cognitive overload while browsing.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.nimh.nih.gov/health/topics/attention-deficit-hyperactivity-disorder-adhd" rel="noopener noreferrer"&gt;NIMH: Attention-Deficit/Hyperactivity Disorder (ADHD)&lt;/a&gt;. Overview of ADHD symptoms, diagnosis, and treatment from the U.S. National Institute of Mental Health.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These sources informed the general idea behind the extension. They do not endorse or validate this specific tool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/google-extension-why-am-i-here" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>tools</category>
    </item>
    <item>
      <title>Forget what you read? Breadcrumb helps</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Thu, 30 Jul 2026 07:30:44 +0000</pubDate>
      <link>https://dev.to/prazian/forget-what-you-read-breadcrumb-helps-48m1</link>
      <guid>https://dev.to/prazian/forget-what-you-read-breadcrumb-helps-48m1</guid>
      <description>&lt;p&gt;You read a great article about Kubernetes autoscaling in March. In July you remember the idea, but not the URL, the title, or even the exact words. You try Google again and hope you find the same page. Developers, students, and researchers hit this constantly: valuable knowledge disappears into browser history.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Breadcrumb&lt;/strong&gt; is a free, open-source Google Chrome extension I built to fix that. Highlight text on any page, save it in one click, and find it again months later with plain-language search. Everything stays on your device. No account, no cloud upload.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chromewebstore.google.com/detail/breadcrumb/medkklaaakhdpgcoaghblbnleeandifi" rel="noopener noreferrer"&gt;Install from the Chrome Web Store&lt;/a&gt; · &lt;a href="https://github.com/yanovian/chrome-ext-breadcrumb" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who is it for?&lt;/li&gt;
&lt;li&gt;How to use it&lt;/li&gt;
&lt;li&gt;What makes it different&lt;/li&gt;
&lt;li&gt;Privacy and permissions&lt;/li&gt;
&lt;li&gt;Open source&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who is it for?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt; saving AWS docs, GitHub issues, Stack Overflow answers, blog posts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Students and researchers&lt;/strong&gt; collecting notes across papers, courses, and articles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI power users&lt;/strong&gt; keeping insights from ChatGPT, Claude, or Gemini that would otherwise vanish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Breadcrumb does not try to change how you work. It captures value from what you already do: read, research, learn.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Save a highlight
&lt;/h3&gt;

&lt;p&gt;Select text on any page. Right-click and choose &lt;strong&gt;Save to Breadcrumb&lt;/strong&gt;. The extension stores the text, page title, link, and timestamp locally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuw6ypu9fsddj0excuwv.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffuw6ypu9fsddj0excuwv.jpg" alt="Save to Breadcrumb from the right-click menu" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Save a highlight from the right-click menu



&lt;h3&gt;
  
  
  2. Open the popup
&lt;/h3&gt;

&lt;p&gt;Click the Breadcrumb icon in your toolbar. Recent saves appear immediately. Search from here, or click &lt;strong&gt;Open library&lt;/strong&gt; for the full view.&lt;/p&gt;

&lt;p&gt;Turn on &lt;strong&gt;Semantic (AI) search&lt;/strong&gt; in settings if you want meaning-based search, not just keywords. The AI runs on your device via Transformers.js. Nothing is uploaded.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnut76i78b8qlvoqgghiz.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnut76i78b8qlvoqgghiz.jpg" alt="Recent saves in the Breadcrumb popup" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Recent saves and quick search in the popup



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi9jmh3vtvkmk2898m13b.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi9jmh3vtvkmk2898m13b.jpg" alt="Popup settings for AI search" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Enable on-device semantic search in settings



&lt;h3&gt;
  
  
  3. Search your library
&lt;/h3&gt;

&lt;p&gt;In the library, type what you remember, like &lt;code&gt;aws&lt;/code&gt; or &lt;code&gt;kubernetes autoscaling&lt;/code&gt;. Breadcrumb finds matching notes even when you do not recall the exact words. Use filters, tags, and the timeline on the right to see what you have been learning over time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm0iirj21wh5uu9si3pvh.jpg" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fm0iirj21wh5uu9si3pvh.jpg" alt="Search results in the Breadcrumb library" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Search results in the library



&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; Highlight, save, search. Your notes stay in your browser only.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes it different
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hybrid search&lt;/strong&gt; blends keyword matching with semantic similarity in one ranked list&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On-device AI&lt;/strong&gt; using a small &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt; model. Works offline. No inference server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Similar notes&lt;/strong&gt; shown when you save something related to an earlier highlight&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning timeline&lt;/strong&gt; with month-by-month breakdown and auto topic tags (AWS, Kubernetes, AI, Rust, and more)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export and delete&lt;/strong&gt; your data as JSON anytime&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Privacy and permissions
&lt;/h2&gt;

&lt;p&gt;Breadcrumb requests only &lt;code&gt;storage&lt;/code&gt;, &lt;code&gt;contextMenus&lt;/code&gt;, and &lt;code&gt;activeTab&lt;/code&gt;. No host permissions, no browsing history tracking, no backend. Notes live in IndexedDB on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open source
&lt;/h2&gt;

&lt;p&gt;The project is MIT licensed. Built with WXT, TypeScript, Vitest, and GitHub Actions CI. Full tutorial: &lt;a href="https://github.com/yanovian/chrome-ext-breadcrumb/blob/master/_doc/tutorial.md" rel="noopener noreferrer"&gt;tutorial on GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/google-extension-breadcrumb" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>ai</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Make dependency updates boring again</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Wed, 29 Jul 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/make-dependency-updates-boring-again-3cfm</link>
      <guid>https://dev.to/prazian/make-dependency-updates-boring-again-3cfm</guid>
      <description>&lt;p&gt;Dependency updates are one of those things teams keep postponing. Not because they do not care, but because every update feels like a risk. A small version bump can break a build, fail tests, or create unexpected issues in production.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;Update Dependencies&lt;/strong&gt;, a GitHub Action that keeps dependencies up to date automatically and opens a pull request, gated on your checks passing when you give it any to run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace/actions/update-dependencies" rel="noopener noreferrer"&gt;Get it on GitHub Marketplace&lt;/a&gt; · &lt;a href="https://github.com/yanovian/update-dependencies-action" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does&lt;/li&gt;
&lt;li&gt;It also protects you from freshly published attacks&lt;/li&gt;
&lt;li&gt;Supported package managers&lt;/li&gt;
&lt;li&gt;Example workflow&lt;/li&gt;
&lt;li&gt;Main inputs&lt;/li&gt;
&lt;li&gt;What the pull request looks like&lt;/li&gt;
&lt;li&gt;Permissions and tokens&lt;/li&gt;
&lt;li&gt;Where it sits next to the bigger names&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;It scans every package manager in your repo, in one run, across every path in a monorepo, not just the root. Every change lands in a pull request that is labeled breaking or non-breaking based on the actual version jump, not just the mode you ran it in.&lt;/p&gt;

&lt;p&gt;If you give it &lt;code&gt;check-commands&lt;/code&gt; (tests, lint, build), a failing update never opens a pull request in the first place. Leave that empty and it will still open one, letting your repo's own pull request CI check the update the same way it checks everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  It also protects you from freshly published attacks
&lt;/h2&gt;

&lt;p&gt;A version that was published an hour ago is not automatically safe just because the version number is higher. A good chunk of recent supply chain attacks worked by publishing a compromised release and letting update bots pick it up within minutes, before anyone noticed. Dependabot addressed this with a minimum release age setting, and Update Dependencies does the same thing.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;min-release-age-days&lt;/code&gt; (default 3) waits out a version's first few days before updating to it. That gives the community a window to catch a bad release before it reaches you. If the newest version is too young, the Action walks back to the newest one that is old enough, skipping any candidate that turns out to itself be vulnerable.&lt;/p&gt;

&lt;p&gt;The one exception: a version that fixes a disclosed vulnerability, checked against the OSV.dev database, always bypasses the wait. Getting a real security fix should never be held up by a policy meant to stop bad ones.&lt;/p&gt;

&lt;p&gt;This check fails open on purpose. If a registry or OSV.dev lookup does not come back in time, the update still goes through, just marked "Unverified" in the pull request instead of blocking the whole run over one slow API. Every pull request gets a "Release-age policy" section explaining exactly why each package was held back, allowed early, or left unverified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supported package managers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Ecosystem&lt;/th&gt;
&lt;th&gt;Language&lt;/th&gt;
&lt;th&gt;What it updates&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;npm, Yarn, pnpm&lt;/td&gt;
&lt;td&gt;JavaScript/TypeScript&lt;/td&gt;
&lt;td&gt;package.json + lockfile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pip&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;requirements.txt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cargo&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;Cargo.toml + Cargo.lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;Go&lt;/td&gt;
&lt;td&gt;go.mod + go.sum&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maven&lt;/td&gt;
&lt;td&gt;Java/JVM&lt;/td&gt;
&lt;td&gt;pom.xml&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gradle&lt;/td&gt;
&lt;td&gt;Java/JVM&lt;/td&gt;
&lt;td&gt;version catalog or build.gradle(.kts)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bundler&lt;/td&gt;
&lt;td&gt;Ruby&lt;/td&gt;
&lt;td&gt;Gemfile + Gemfile.lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composer&lt;/td&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;composer.json + composer.lock&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NuGet&lt;/td&gt;
&lt;td&gt;C#/.NET&lt;/td&gt;
&lt;td&gt;*.csproj&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Example workflow
&lt;/h2&gt;

&lt;p&gt;Save this as &lt;code&gt;.github/workflows/update-dependencies.yml&lt;/code&gt;. This is the recommended setup: no &lt;code&gt;check-commands&lt;/code&gt;, a personal access token for &lt;code&gt;github-token&lt;/code&gt; so your repo's own pull request CI runs on the update, and no trigger on &lt;code&gt;pull_request&lt;/code&gt; (the FAQ in the repo explains why).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update Dependencies&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1'&lt;/span&gt; &lt;span class="c1"&gt;# every Monday at 02:00 UTC&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;update&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yanovian/update-dependencies-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;update-strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;non-breaking&lt;/span&gt;
          &lt;span class="na"&gt;create-pull-request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;github-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PAT_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Main inputs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;update-strategy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;non-breaking&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;keep every package within its current major version, or allow major jumps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;check-commands&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;(empty)&lt;/td&gt;
&lt;td&gt;commands to run after updating, one per line; all must exit 0 or no pull request opens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min-release-age-days&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;minimum days a version must have been published before updating to it; a fix for a known vulnerability always bypasses this&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;create-pull-request&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;whether to open a pull request when updates are available and checks pass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;base-branch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;repo default branch&lt;/td&gt;
&lt;td&gt;branch the pull request is opened against&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;branch-name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chore/update-deps/&amp;lt;update-strategy&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;prefix for the branch; the actual branch is &lt;code&gt;&amp;lt;branch-name&amp;gt;/&amp;lt;run-date&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;config-path&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.github/update-dependencies.yml&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;path to a config file to skip an ecosystem or a path; missing is fine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;working-directory&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;directory to scan, relative to the repo root&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;github-token&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;${{ github.token }}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;token used to push the branch and open the pull request; a PAT is recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What the pull request looks like
&lt;/h2&gt;

&lt;p&gt;For every path in your repo where something changed, the description lists the package, the path, the version it moved from and to, and whether that change was breaking. It also lists every command that ran and passed, and explains why keeping dependencies current matters for security, while making clear that testing the change is still on you.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fveyx5xcqezynww42hwk5.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fveyx5xcqezynww42hwk5.png" alt="A pull request opened by Update Dependencies, showing the run date, a table of package version changes, and the security and testing-responsibility note" width="800" height="889"&gt;&lt;/a&gt;&lt;/p&gt;
A pull request opened by Update Dependencies



&lt;p&gt;Running it again the same day updates that same pull request instead of opening a new one. A run on a later date opens a new one, and if an earlier one from this Action is still open, the new pull request points to it and recommends closing it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions and tokens
&lt;/h2&gt;

&lt;p&gt;Your workflow needs &lt;code&gt;contents: write&lt;/code&gt; and &lt;code&gt;pull-requests: write&lt;/code&gt; either way. For &lt;code&gt;github-token&lt;/code&gt;, a PAT is recommended so your repo's own pull request CI runs on the update automatically; the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; also works, paired with &lt;code&gt;check-commands&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If it can open a pull request only once your commands all pass, that is a real signal, but not a guarantee. Review the diff yourself before merging, especially for a breaking update.&lt;/p&gt;

&lt;p&gt;The goal is simple: make dependency updates a regular habit instead of a stressful emergency task. Run it on a schedule, review the changes, and most of the time simply merge. Keep dependencies fresh, reduce security risks, and avoid months of accumulated updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it sits next to the bigger names
&lt;/h2&gt;

&lt;p&gt;On the specific problem of updating a version without opening the door to a supply chain attack, this is doing what Dependabot does with its own minimum release age, plus a vulnerability check that decides when it is safe to skip the wait.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Update Dependencies&lt;/th&gt;
&lt;th&gt;Dependabot&lt;/th&gt;
&lt;th&gt;Renovate&lt;/th&gt;
&lt;th&gt;Paid SCA tools (Snyk, Mend)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Minimum release age gate&lt;/td&gt;
&lt;td&gt;Yes, configurable&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vulnerability-aware bypass&lt;/td&gt;
&lt;td&gt;Yes (OSV.dev)&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (proprietary feeds)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;Free self-hosted / paid hosted&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;License and reachability scanning&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;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;It is not a replacement for a full paid SCA product, it does not do license scanning or reachability analysis. But for the one job it is built for, it is not missing the security feature that actually matters here.&lt;/p&gt;

&lt;p&gt;For the license part specifically, pair it with &lt;a href="https://pooyan.info/articles/open-license-auditor-github-action" rel="noopener noreferrer"&gt;Open License Auditor&lt;/a&gt;, another Action I built, which scans your dependency tree for risky and unidentified licenses on every pull request.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/update-dependencies-github-action" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>security</category>
      <category>opensource</category>
      <category>devops</category>
    </item>
    <item>
      <title>Clean up years of GitHub Actions runs automatically</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Tue, 28 Jul 2026 07:30:45 +0000</pubDate>
      <link>https://dev.to/prazian/clean-up-years-of-github-actions-runs-automatically-33pe</link>
      <guid>https://dev.to/prazian/clean-up-years-of-github-actions-runs-automatically-33pe</guid>
      <description>&lt;p&gt;Every workflow run stays in your Actions history forever, unless you clean it up yourself. After a year or two of CI, that history turns into thousands of runs nobody will ever open again. Scrolling through them to find anything useful becomes painful.&lt;/p&gt;

&lt;p&gt;That is why I built &lt;strong&gt;Prune Old GitHub Actions Runs&lt;/strong&gt;, a GitHub Action that deletes workflow runs older than a number of days you choose, on a schedule.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/marketplace/actions/prune-old-github-actions-runs" rel="noopener noreferrer"&gt;Get it on GitHub Marketplace&lt;/a&gt; · &lt;a href="https://github.com/yanovian/prune-old-actions" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What it does&lt;/li&gt;
&lt;li&gt;Inputs&lt;/li&gt;
&lt;li&gt;Example workflow&lt;/li&gt;
&lt;li&gt;Permissions and tokens&lt;/li&gt;
&lt;li&gt;Why it matters&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;You give it a token and a number of days. Anything older than that gets deleted. You can also tell it to always keep the N most recent runs, regardless of age, so a workflow you rarely trigger does not lose its entire history. A dry-run mode lists what it would delete without deleting anything, which is worth running once before you trust it with the real thing.&lt;/p&gt;

&lt;p&gt;Deletion is permanent and cannot be undone, so start with dry-run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inputs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Required&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;GitHub token for authentication (use &lt;code&gt;${{ secrets.GITHUB_TOKEN }}&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;days-ago&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;number of days to look back when identifying old runs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dry-run&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;when true, lists runs without deleting them&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keep-latest&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;preserves the most recent N runs; &lt;code&gt;0&lt;/code&gt; disables this&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Example workflow
&lt;/h2&gt;

&lt;p&gt;Save this as a scheduled workflow, for example &lt;code&gt;.github/workflows/prune-old-actions.yml&lt;/code&gt;. Test with &lt;code&gt;dry-run&lt;/code&gt; first:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;cron&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*'&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prune-old-actions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v7&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yanovian/prune-old-actions@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;days-ago&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
          &lt;span class="na"&gt;dry-run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;keep-latest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you have checked the dry-run output and it deletes what you expect, drop &lt;code&gt;dry-run&lt;/code&gt; (or set it to &lt;code&gt;false&lt;/code&gt;) and let it run for real on the same schedule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Permissions and tokens
&lt;/h2&gt;

&lt;p&gt;Deleting workflow runs needs a token with write access to the Actions scope. The default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; works if your workflow grants &lt;code&gt;actions: write&lt;/code&gt;; a scoped personal access token or a GitHub App token are the more locked-down alternatives if you would rather not give the default token that reach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it matters
&lt;/h2&gt;

&lt;p&gt;The goal is simple: keep your Actions history relevant and your repository light, without spending time deleting runs by hand every few months. Set the retention window once, run it on a schedule, and forget about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/prune-old-github-actions-runs" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>devops</category>
      <category>opensource</category>
      <category>automation</category>
    </item>
    <item>
      <title>From "spaghetti code" to "spaghetti architecture" 🍝</title>
      <dc:creator>Pooyan Razian</dc:creator>
      <pubDate>Mon, 27 Jul 2026 07:30:44 +0000</pubDate>
      <link>https://dev.to/prazian/from-spaghetti-code-to-spaghetti-architecture-3b7o</link>
      <guid>https://dev.to/prazian/from-spaghetti-code-to-spaghetti-architecture-3b7o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; All the names and events in this story are fictional, and any resemblance to real people or events is purely coincidental.&lt;br&gt;
&lt;strong&gt;The story is completely made-up&lt;/strong&gt; but is inspired by a mix of &lt;strong&gt;a few common patterns&lt;/strong&gt; I have either seen myself or heard from others in the past few years.&lt;br&gt;
The purpose of this story is to share a common trending scenario and a few mistakes that can cause IT-based startups to fail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler alert:&lt;/strong&gt; This article might refer to some 100x delicious dependencies in different layers. 😋&lt;/p&gt;

&lt;p&gt;OK, here the story begins ✨&lt;/p&gt;

&lt;p&gt;Seven years ago, during the IT hype, Mark took a few courses to learn web development using HTML, CSS, JavaScript, PHP, and MySQL.&lt;br&gt;
Then he was hired by a startup as a web developer. His main task was building the application's frontend using jQuery and later with React. Gradually, he also learned how to build backend APIs using Node.js and Express. He was the company's full-stack developer at this point. 🥳&lt;/p&gt;

&lt;p&gt;Back then, they had one extensive "old" application that no one dared to touch and a new one built with a cleaner approach. The old code had files containing thousands of lines of code. A mix of backend logic, database queries, jQuery, HTML, and CSS. A small fix or a single change in one part of the code could break 10 more things! 🍝&lt;br&gt;
He could easily see how difficult it was to maintain and extend the old application, and he always wanted to avoid making the same mistakes as the previous developers had made. It is always "others" that make mistakes, right? 😉&lt;br&gt;
He studied and practiced design patterns to write cleaner code.&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fsjg6cmv0i0hwvzsmoqny.png" class="article-body-image-wrapper"&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%2Fsjg6cmv0i0hwvzsmoqny.png" alt="Don't know what it does - My code - programmer's joke" width="500" height="520"&gt;&lt;/a&gt;&lt;/p&gt;
Don't know what it does - My code - programmer's joke



&lt;p&gt;A few years later, he was approached by a recruiter on LinkedIn for a CTO position in a retailer startup. He was living in a small country and knew that companies are desperate to find technical staff in that region, but he was not expecting to be offered a CTO position. He was unsure if he was ready for that, but after a few interviews, he was hired for the position. He was surprised and excited at the same time! The company was in its initial stage and did not have enough money to hire more developers, so he had to do everything by himself.&lt;/p&gt;

&lt;p&gt;He knew that he had to learn a lot to build the product. Mark had a friend named Alex, a technical manager at another startup. He asked him for advice. Alex told him that in their company, they were using TypeScript for frontend, backend, and even for writing their Infrastructure as Code (IaC). To Mark, this sounded great because then he could do everything by just learning one programming language that was not even very different from the JavaScript that he already knew!&lt;br&gt;
This felt like "the answer" to everything he was expected to do in this new position. 🎉 Alex also said that recently in a technical meetup, he had heard about a new thing called "serverless computing" and "serverless architecture" that could apparently simplify things.&lt;br&gt;
He also mentioned things like lambda functions and API Gateway that Mark had never used before.&lt;/p&gt;

&lt;p&gt;Soon after, Mark learned TypeScript basics and tried AWS CDK (Cloud Development Kit) to build a few simple lambda functions. He was amazed by how easy it was to build and deploy a lambda function on AWS. He then learned to use API Gateway to create REST APIs and connect them together. He also learned how to start an RDS instance (MySQL) and connect it to these lambda functions using CDK. He could build his first simple CRUD application in a very short time!&lt;/p&gt;

&lt;p&gt;Time passed, and the company grew. They hired more developers, and Mark taught them how to use these technologies.&lt;br&gt;
Also, one of the new seniors shared with the team how to use unit tests, and then they added a check in their pipeline to run all these tests before deploying the code.&lt;br&gt;
The company could not afford to hire architects, DevOps engineers, or SysAdmins because they thought &lt;strong&gt;a)&lt;/strong&gt; they were too expensive and &lt;strong&gt;b)&lt;/strong&gt; a small company like that doesn't need such skills.&lt;/p&gt;

&lt;p&gt;In the beginning, everything was fine. They could build the MVP in a few years and successfully deliver it to their first 1,000 customers. Developers were happy because they could build things quickly, and the management was happy about the overall price and development speed.&lt;/p&gt;

&lt;p&gt;After a while, now that they were using one database shared with all lambda functions, they realized even a small change in one of the services could sometimes break everything else! They were also facing some random connection issues with the database. After consulting with a few people, they decided to make these services less dependent and split the database. By then, they had hundreds of lambda functions and a couple of API Gateways, so having one RDS instance for each service was not an option. Mark spoke with his friend Alex again, and he suggested DynamoDB. Mark didn't know much about the difference between relational and NoSQL databases, or even if there are different types of such databases, but it was quite easy for him to create DynamoDB tables using CDK and use the new query syntax in his code. He mainly liked DynamoDB because he could easily create new tables without having to instantiate a database engine, define the schema, or deal with VPC, Security Groups, etc. Everything seemed very simple. To simplify things a bit more, he even used non-VPC lambda functions. At this point, they were still in the early stages and had no strict compliance requirements. At least, that's what they thought.&lt;/p&gt;

&lt;p&gt;Even though it took a while to migrate all the data and change the queries in the code, after the migration, everyone was happy not having to deal with database-level relations of data, VPC, Security Groups, and other networking and security stuff anymore.&lt;/p&gt;

&lt;p&gt;Meanwhile, they had hired a data scientist, Anna, to help business have a better overview. Unlike the dev team, she was mainly using Python, and she could not use AWS the way that the team was using it through CDK and TypeScript.&lt;br&gt;
She had to ask the dev team to create her databases and other tools that she needed. But still, she had to do everything from her laptop, because the dev team didn't want to see Python as an option and wanted everyone to use the same programming language and promote the "lovely framework" they had already built. (lambda functions, TypeScript, and their smart set of customizations to enable logging, etc.)&lt;/p&gt;

&lt;h2&gt;
  
  
  When the pile of poo started to smell 💩
&lt;/h2&gt;

&lt;p&gt;The team was small, so they could not afford to separate the codebase for every single lambda function, so they decided to put all the code in one repository and reuse different parts of the code and libraries for convenience.&lt;br&gt;
They were using TypeScript, so they could easily import and reuse different parts of the code (modules) in different lambda functions.&lt;/p&gt;

&lt;p&gt;In order to reduce the size of lambda functions, they decided to use standard Step Functions (State Machines) to split the logic into smaller parts and move some of the decision makings out of lambda functions. Soon they realized different people on the same team needed a lot of coordination and communication to make sure they are not breaking each other's code because in designing a workflow, the concept of "interface" simply doesn't exist. That means a simple change in the data structure in one layer could easily break the next ones in the chain.&lt;/p&gt;

&lt;p&gt;After a while, they realized different parts of their system have silently become dependent on each other. At this point, they had a few lambda layers that almost every lambda function was using and CloudFormation stacks that were dependent on each other. Long-lasting state-aware Step Functions could not be easily modified or removed. Even though Mark wanted to avoid the maintenance hell of a tightly-coupled monolith that he had experienced in his previous jobs, soon, a single change in one lambda function or a lambda layer could break the whole thing!&lt;/p&gt;

&lt;p&gt;&lt;a href="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%2Fpkhmxu59txrsguh8590d.png" class="article-body-image-wrapper"&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%2Fpkhmxu59txrsguh8590d.png" alt="Don't know what it does - lambda function - programmer's joke" width="500" height="520"&gt;&lt;/a&gt;&lt;/p&gt;
Don't know what it does - lambda function - programmer's joke



&lt;p&gt;Mark was not happy with the situation, but he didn't want to admit the mistake and find a solution for it, so he simply quit his job and went to another company. Later, the company, now a scaleup, hired a new CTO named Juliet.&lt;/p&gt;

&lt;p&gt;At this time, the company had enough money to hire a manager who had worked for a few large companies and a few more managers to help her lead their IT. None of them had hands-on IT experience, but most had a good reputation in the industry and were quite good at people management.&lt;/p&gt;

&lt;p&gt;The new CTO, Juliet, was a nice person but had no hands-on background in software development and was not aware of the practical and architectural challenges in this field. So she was not experienced enough to see the existing problems and was not confident enough to guide the existing team to make the strategic changes that were necessary at this point. The company continued with the same practices and habits, but the solution became increasingly slow and even exponentially complex. For each task, multiple services had to communicate with each other and wait for the response synchronously. The system was very slow, and sometimes requests were timing out. Having an overview of services and their dependencies and data flow was almost impossible. Error handling was very complex, and debugging was a nightmare... To fix errors, sometimes they were manually invoking failed lambda functions again to see if the error would be gone, but soon they realized due to not having thought about the idempotency of functions, they had ended up with some unwanted double payments or double item shipping!&lt;br&gt;
Fortunately, the damage was not too big, but it was still a big problem in the eyes of customers and business.&lt;br&gt;
At this point, it was even becoming more and more difficult to identify potential fraudulent activities from thousands of common system errors.&lt;br&gt;
Also, they could see some wired scenarios where a dynamically-typed language like JavaScript could cause random bugs in financial calculations that were sometimes difficult to identify or reproduce.&lt;/p&gt;

&lt;p&gt;This led to frustration in the management and technical staff. The company started to lose its best developers. They had difficulties hiring new senior staff willing to continue building on top of this. Even though developers mostly had to work overtime, unlike the good old days, they could not meet their deadlines. Also, the quality of their product was so bad that they started to lose key customers. The business was not going well, and the owners decided to sell the company for cheap.&lt;/p&gt;

&lt;p&gt;To save the business, the new owner had to hire an expensive team of external consultants to redesign and re-architect the solution and even build some parts of it from scratch.&lt;br&gt;
Juliet also left the company and soon joined another medium-sized company as a VP of engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;p&gt;It is good to remember and remind each other that:&lt;/p&gt;

&lt;p&gt;✅ Communication over the network is &lt;strong&gt;slower&lt;/strong&gt;, &lt;strong&gt;less reliable&lt;/strong&gt;, and is also considered to be less secure.&lt;/p&gt;

&lt;p&gt;✅ Serverless computing does not necessarily mean FaaS or "Lambda functions"! It is a much broader concept.&lt;/p&gt;

&lt;p&gt;✅ Thanks to the initial misunderstanding around AWS SAM (Serverless Application Model), these days, "extensively using Lambda functions for building everything" is commonly thought to be the "serverless architecture".&lt;/p&gt;

&lt;p&gt;✅ There are other serverless options in AWS, like &lt;strong&gt;AWS Fargate&lt;/strong&gt;, that can help you use your software frameworks of choice (instead of ending up building your own framework) with more standard tooling like containers (ECS, with the least effort, or EKS, with more customization and a wider ecosystem - CNCF)&lt;/p&gt;

&lt;p&gt;✅ In a microservice architecture, the &lt;strong&gt;size (of each service) matters&lt;/strong&gt;! You might want to call them micro-service, nano-service, or whatever, but that has a huge impact on data flow, the amount of duplicated data, network traffic, service communication rates, etc.&lt;/p&gt;

&lt;p&gt;✅ It is important to remember that you can split complexity to make it easier for different teams to work on them independently (only if you can manage to reduce dependency), but it never dies! It might even grow 10x somewhere else, so then you need to hire people to deal with that.&lt;/p&gt;

&lt;p&gt;✅ Remember, debugging a distributed system is usually much more complex than looking at a single stack trace.&lt;/p&gt;

&lt;p&gt;✅ Remember, achieving data consistency is a big challenge in distributed systems.&lt;/p&gt;

&lt;p&gt;✅ Remember, things look great when you only hear about the benefits and success stories. Let's avoid marketing traps and fancy buzzwords when we are supposed to build important systems for our customers and societies.&lt;/p&gt;

&lt;p&gt;✅ Remember, handling "distributed transactions" can be quite challenging. Using a single transactional database, you can simply roll back the whole transaction if something fails or is invalid, right?&lt;br&gt;
But what if you have 10+ services writing into their own databases, and then the 11th fails?&lt;br&gt;
What pattern should you use? Saga? Two phase commit? Compensating transaction? ... or just have an exponential retry mechanism? etc.&lt;/p&gt;

&lt;p&gt;✅ Remember, microservice architecture was initiated to solve the problem for large companies and corporations with hundreds, not if thousands, of developers having had to work on a single giant monolith.&lt;br&gt;
It is not necessarily the best option for small startups with a few junior developers.&lt;/p&gt;

&lt;p&gt;✅ Remember, microservice architecture is supposed to help you &lt;strong&gt;reduce the complexity&lt;/strong&gt; by &lt;strong&gt;reducing the size and dependencies&lt;/strong&gt; and moving it to another layer for someone else in your team/organization with a different set of skills to deal with, so if you still have a single shared database or a single codebase where all the services are dependent on each other, you are probably only getting the disadvantages of both worlds!&lt;/p&gt;

&lt;p&gt;✅ Remember, hundreds of smart developers might have spent years to build secure software frameworks with a lot of tooling out of the box for you, and you are probably not going to build something better than that in a few months.&lt;/p&gt;

&lt;p&gt;✅ In order to build a skyscraper or even a tall building, you first need to design the architecture, and then you should consult with construction engineers to verify that, and then begin by building a strong foundation.&lt;br&gt;
&lt;strong&gt;You can't start the project from the penthouse!&lt;/strong&gt; The same applies to software.&lt;/p&gt;

&lt;p&gt;Let's use the tools for what they are built for. Lambda and any other FaaS solutions are great for many use cases, but they are not "the answer to everything!" and are not the only serverless options.&lt;/p&gt;

&lt;p&gt;You can leverage the power of serverless by choosing the right tools based on the use-case. Lambda, ECS (+Fargate), EKS (+Fargate), ... depending on the size of your organization, the size and complexity of your solutions, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article was originally published at &lt;a href="https://pooyan.info/articles/from-spaghetti-code-to-spaghetti-architecture" rel="noopener noreferrer"&gt;pooyan.info&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;





&lt;p&gt;If you liked the article, feel free to share it with your friends, family, or colleagues. You can also follow me on &lt;a href="https://www.linkedin.com/in/prazian/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Copyright &amp;amp; Disclaimer
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;All content provided on this article is for informational and educational purposes only. The author makes no representations as to the accuracy or completeness of any information on this site or found by following any link on this site.&lt;/li&gt;
&lt;li&gt;All the content is copyrighted, except the assets and content I have referenced to other people's work, and may not be reproduced on other websites, blogs, or social media. You are not allowed to reproduce, summarize to create derivative work, or use any content from this website under your name. This includes creating a similar article or summary based on AI/GenAI. For educational purposes, you may refer to parts of the content, and only refer, but you must provide a link back to the original article on this website. This is allowed only if your content is less than 10% similar to the original article.&lt;/li&gt;
&lt;li&gt;While every care has been taken to ensure the accuracy of the content of this website, I make no representation as to the accuracy, correctness, or fitness for any purpose of the site content, nor do I accept any liability for loss or damage (including consequential loss or damage), however caused, which may be incurred by any person or organization from reliance on or use of information on this site.&lt;/li&gt;
&lt;li&gt;The contents of this article should not be construed as legal advice.&lt;/li&gt;
&lt;li&gt;Opinions are my own and not the views of my employer.&lt;/li&gt;
&lt;li&gt;English is not my mother-tongue language, so even though I try my best to express myself correctly, there might be a chance of miscommunication.&lt;/li&gt;
&lt;li&gt;Links or references to other websites, including the use of information from 3rd-parties, are provided for the benefit of people who use this website. I am not responsible for the accuracy of the content on the websites that I have put a link to and I do not endorse any of those organizations or their contents.&lt;/li&gt;
&lt;li&gt;If you have any queries or if you believe any information on this article is inaccurate, or if you think any of the assets used in this article are in violation of copyright, please &lt;a href="https://pooyan.info/contact" rel="noopener noreferrer"&gt;contact me&lt;/a&gt; and let me know.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>architecture</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
