<?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: SANKET PATIL</title>
    <description>The latest articles on DEV Community by SANKET PATIL (@sanket00123).</description>
    <link>https://dev.to/sanket00123</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%2F990686%2F9b9beaff-2d6d-4de4-8f83-efa4441d03a0.png</url>
      <title>DEV Community: SANKET PATIL</title>
      <link>https://dev.to/sanket00123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sanket00123"/>
    <language>en</language>
    <item>
      <title>My Journey to Passing AZ-900: Microsoft Azure Fundamentals</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Mon, 22 Jun 2026 06:45:51 +0000</pubDate>
      <link>https://dev.to/sanket00123/my-journey-to-passing-az-900-microsoft-azure-fundamentals-i06</link>
      <guid>https://dev.to/sanket00123/my-journey-to-passing-az-900-microsoft-azure-fundamentals-i06</guid>
      <description>&lt;p&gt;Recently, I achieved the Microsoft Azure Fundamentals (AZ-900) certification. While the certification is considered an entry-level Azure exam, the journey taught me several valuable lessons about cloud computing, exam preparation, and continuous learning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Decided to Pursue AZ-900
&lt;/h2&gt;

&lt;p&gt;As a software engineer, I wanted to strengthen my understanding of cloud concepts and Azure services. Although I work primarily in application development, cloud technologies have become an essential part of modern software delivery. AZ-900 provided a structured way to build foundational knowledge across cloud concepts, architecture, security, governance, networking, storage, and cost management.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Preparation Approach
&lt;/h2&gt;

&lt;p&gt;I primarily relied on Microsoft Learn modules and practice assessments. Initially, I focused on understanding concepts rather than memorizing answers. Topics such as cloud service models (IaaS, PaaS, SaaS), Azure regions, availability zones, virtual networks, storage services, and governance tools formed the core of my preparation.&lt;/p&gt;

&lt;p&gt;One of the biggest lessons I learned was that understanding the differences between similar services is critical. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Azure Policy vs RBAC&lt;/li&gt;
&lt;li&gt;Azure Monitor vs Application Insights&lt;/li&gt;
&lt;li&gt;VPN Gateway vs ExpressRoute&lt;/li&gt;
&lt;li&gt;Azure Advisor vs Azure Migrate&lt;/li&gt;
&lt;li&gt;Availability Zones vs Region Pairs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many exam questions are scenario-based and require understanding when to use a specific service rather than simply knowing its definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges During Preparation
&lt;/h2&gt;

&lt;p&gt;Practice assessments were not always consistent. My scores fluctuated across attempts, which was initially discouraging. Some assessments focused heavily on governance and monitoring, while others emphasized architecture and networking concepts.&lt;/p&gt;

&lt;p&gt;Instead of focusing solely on scores, I reviewed every incorrect answer and created flashcards for recurring weak areas. This approach helped me improve my understanding and confidence over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Exam Experience
&lt;/h2&gt;

&lt;p&gt;The exam tested both foundational concepts and practical scenarios. Reading questions carefully was important because Microsoft often includes keywords that point directly to the correct service or feature.&lt;/p&gt;

&lt;p&gt;A few tips from my experience:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand concepts instead of memorizing answers.&lt;/li&gt;
&lt;li&gt;Focus on service selection scenarios.&lt;/li&gt;
&lt;li&gt;Review governance and monitoring topics thoroughly.&lt;/li&gt;
&lt;li&gt;Use practice assessments to identify weak areas.&lt;/li&gt;
&lt;li&gt;Stay calm during the exam and avoid overthinking questions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;I successfully passed the AZ-900 certification exam and earned the Microsoft Azure Fundamentals certification.&lt;/p&gt;

&lt;p&gt;More importantly, the journey improved my understanding of cloud computing fundamentals and provided a stronger foundation for future Azure learning paths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;Certification is not just about passing an exam. It is about building confidence, learning new concepts, and creating a foundation for future growth. Every practice test, mistake, and revision contributed to the final outcome.&lt;/p&gt;

&lt;p&gt;For anyone considering AZ-900, my advice is simple: focus on understanding the concepts, practice consistently, and don't get discouraged by practice assessment scores. Progress matters more than perfection.&lt;/p&gt;

</description>
      <category>cloudcomputing</category>
      <category>az900</category>
      <category>azurefundamentals</category>
      <category>azure</category>
    </item>
    <item>
      <title>Fixing Bugs Is Easy. Preventing Their Return Is Hard</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Fri, 12 Jun 2026 08:20:17 +0000</pubDate>
      <link>https://dev.to/sanket00123/fixing-bugs-is-easy-preventing-their-return-is-hard-jkb</link>
      <guid>https://dev.to/sanket00123/fixing-bugs-is-easy-preventing-their-return-is-hard-jkb</guid>
      <description>&lt;p&gt;Most developers celebrate when they identify the root cause of a bug.&lt;/p&gt;

&lt;p&gt;The debugger finally reveals the problem. The fix is coded. Tests pass. A pull request is raised.&lt;/p&gt;

&lt;p&gt;But in my experience, finding and fixing the bug is often the easiest part of the process.&lt;/p&gt;

&lt;p&gt;The real challenge is proving that the fix is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Illusion of a Successful Fix
&lt;/h2&gt;

&lt;p&gt;A common mistake is to focus only on making the reported issue disappear.&lt;/p&gt;

&lt;p&gt;Imagine a mobile application crashes when a user performs a specific action. After investigating, we discover an exception being thrown from an asynchronous operation. We add exception handling, verify the crash no longer occurs, and consider the issue resolved.&lt;/p&gt;

&lt;p&gt;The problem is that we only answered one question:&lt;/p&gt;

&lt;p&gt;"Does the application still crash?"&lt;/p&gt;

&lt;p&gt;We didn't answer the more important question:&lt;/p&gt;

&lt;p&gt;"Did we actually fix the underlying problem without breaking anything else?"&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptoms vs Root Causes
&lt;/h2&gt;

&lt;p&gt;One lesson I've learned is that symptoms and root causes are rarely the same thing.&lt;/p&gt;

&lt;p&gt;A crash report may point to a particular line of code, but that line is often just where the failure becomes visible.&lt;/p&gt;

&lt;p&gt;Before implementing any fix, I try to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why did the system enter this state?&lt;/li&gt;
&lt;li&gt;What assumptions were violated?&lt;/li&gt;
&lt;li&gt;What conditions allowed the issue to occur?&lt;/li&gt;
&lt;li&gt;Could the same root cause appear somewhere else?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treating symptoms instead of causes often leads to recurring bugs that reappear weeks later under slightly different conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Regression Question
&lt;/h2&gt;

&lt;p&gt;Every bug fix introduces risk.&lt;/p&gt;

&lt;p&gt;When reviewing a fix, I always ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What behavior changed?&lt;/li&gt;
&lt;li&gt;Which users are affected?&lt;/li&gt;
&lt;li&gt;Which code paths are now different?&lt;/li&gt;
&lt;li&gt;What existing functionality depends on this logic?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A fix that solves one issue but creates two new ones is not really a fix.&lt;/p&gt;

&lt;p&gt;This is why regression validation is often more important than writing the code change itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confidence Over Hope
&lt;/h2&gt;

&lt;p&gt;Many teams validate fixes with a simple process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reproduce the bug.&lt;/li&gt;
&lt;li&gt;Apply the fix.&lt;/li&gt;
&lt;li&gt;Verify the bug no longer occurs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While necessary, this is rarely sufficient.&lt;/p&gt;

&lt;p&gt;I prefer adding additional validation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test edge cases.&lt;/li&gt;
&lt;li&gt;Test failure scenarios.&lt;/li&gt;
&lt;li&gt;Review related code paths.&lt;/li&gt;
&lt;li&gt;Consider platform-specific behavior.&lt;/li&gt;
&lt;li&gt;Verify assumptions made by the fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to prove the fix works once.&lt;/p&gt;

&lt;p&gt;The goal is to build confidence that it continues to work under real-world conditions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Best Fixes Prevent Future Bugs
&lt;/h2&gt;

&lt;p&gt;The highest-quality fixes often do more than resolve the current issue.&lt;/p&gt;

&lt;p&gt;They make similar issues harder to introduce in the future.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding defensive error handling.&lt;/li&gt;
&lt;li&gt;Improving logging and observability.&lt;/li&gt;
&lt;li&gt;Removing unsafe assumptions.&lt;/li&gt;
&lt;li&gt;Strengthening automated tests.&lt;/li&gt;
&lt;li&gt;Simplifying complex logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A bug fix should improve the system, not just patch a hole.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Over time, I've realized that debugging is only one part of software engineering.&lt;/p&gt;

&lt;p&gt;Finding the bug demonstrates technical skill.&lt;/p&gt;

&lt;p&gt;Designing a safe fix demonstrates engineering judgment.&lt;/p&gt;

&lt;p&gt;The next time you solve a production issue, don't stop after the error disappears.&lt;/p&gt;

&lt;p&gt;Ask yourself a harder question:&lt;/p&gt;

&lt;p&gt;"How confident am I that this won't happen again?"&lt;/p&gt;

&lt;p&gt;That's where the real work begins.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>career</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Production Systems Fail in Ways Tutorials Never Discuss</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Fri, 06 Mar 2026 11:52:01 +0000</pubDate>
      <link>https://dev.to/sanket00123/production-systems-fail-in-ways-tutorials-never-discuss-533e</link>
      <guid>https://dev.to/sanket00123/production-systems-fail-in-ways-tutorials-never-discuss-533e</guid>
      <description>&lt;p&gt;Most engineers think of bugs as something technical.&lt;/p&gt;

&lt;p&gt;A broken query.&lt;br&gt;
A race condition.&lt;br&gt;
A missing index.&lt;/p&gt;

&lt;p&gt;You fix it, deploy a hotfix, and move on.&lt;/p&gt;

&lt;p&gt;But sometimes a “bug” reveals something much deeper - not just about the system, but about &lt;strong&gt;how software businesses actually work&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Recently, I faced one such situation that changed how I think about production systems, ownership, and responsibility as a senior engineer.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Performance Issue That Didn’t Make Sense
&lt;/h2&gt;

&lt;p&gt;A customer reported that the application had become &lt;strong&gt;very slow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Naturally, the first place we checked was the application infrastructure.&lt;/p&gt;

&lt;p&gt;The application was running on an Azure App Service plan &lt;strong&gt;P1v3&lt;/strong&gt;, which is a reasonably capable tier. When we looked at the metrics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CPU utilization was below &lt;strong&gt;60%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Memory looked stable&lt;/li&gt;
&lt;li&gt;No major spikes in requests&lt;/li&gt;
&lt;li&gt;No error rates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the application side, &lt;strong&gt;everything looked normal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So the question became:&lt;/p&gt;

&lt;p&gt;If the application server is healthy, &lt;strong&gt;why is the app slow?&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The First Clue: Local Environment Was Fast
&lt;/h2&gt;

&lt;p&gt;When we tested the application locally using a restored database backup, the performance was &lt;strong&gt;significantly faster&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That was the moment we realized:&lt;/p&gt;

&lt;p&gt;This might not be an application problem.&lt;/p&gt;

&lt;p&gt;This might be a &lt;strong&gt;database problem&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Real Culprit: A $5 Database Plan
&lt;/h2&gt;

&lt;p&gt;After investigating the database metrics, we finally found the issue.&lt;/p&gt;

&lt;p&gt;The production database was running on a &lt;strong&gt;$5 basic plan&lt;/strong&gt;, and it was consistently hitting &lt;strong&gt;100% utilization&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The application itself was fine.&lt;/p&gt;

&lt;p&gt;But the database simply &lt;strong&gt;did not have enough resources to handle the workload&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the database became the bottleneck, every request slowed down - giving the impression that the entire system was performing poorly.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Awkward Truth: We Had Recommended This Earlier
&lt;/h2&gt;

&lt;p&gt;The uncomfortable part of this situation was that this wasn’t completely unexpected.&lt;/p&gt;

&lt;p&gt;Earlier in the project we had recommended:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Start with the basic plan and &lt;strong&gt;upgrade the database as data grows.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a common and reasonable approach during early deployments.&lt;/p&gt;

&lt;p&gt;But like many things in production systems, &lt;strong&gt;it was never revisited again&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The system kept growing.&lt;br&gt;
The data increased.&lt;br&gt;
Usage increased.&lt;/p&gt;

&lt;p&gt;But the database plan stayed the same.&lt;/p&gt;

&lt;p&gt;Eventually the performance issue surfaced - and the customer reported it as a &lt;strong&gt;bug&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Engineering Instinct: Just Fix It
&lt;/h2&gt;

&lt;p&gt;As engineers, our instinct is simple:&lt;/p&gt;

&lt;p&gt;Fix the problem.&lt;/p&gt;

&lt;p&gt;So the immediate solution was obvious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgrade the database tier&lt;/li&gt;
&lt;li&gt;Monitor performance&lt;/li&gt;
&lt;li&gt;Verify application responsiveness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And technically, that would resolve the issue.&lt;/p&gt;

&lt;p&gt;But this is where I learned something new - something that tutorials never teach.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Business Reality of Fixed-Price Projects
&lt;/h2&gt;

&lt;p&gt;This project had been delivered as a &lt;strong&gt;fixed-price engagement&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In such projects, development and delivery are scoped within an agreed cost.&lt;/p&gt;

&lt;p&gt;But what happens months later when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure needs adjustment&lt;/li&gt;
&lt;li&gt;External services change policies&lt;/li&gt;
&lt;li&gt;Usage grows beyond initial assumptions&lt;/li&gt;
&lt;li&gt;Performance tuning becomes necessary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Are these &lt;strong&gt;bugs&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Or are they &lt;strong&gt;support and maintenance work&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;This is where things get complicated.&lt;/p&gt;

&lt;p&gt;Startups and small teams often fall into a trap:&lt;/p&gt;

&lt;p&gt;They keep fixing things for free because it feels like the “right thing to do.”&lt;/p&gt;

&lt;p&gt;But over time, this creates a hidden cost for the company.&lt;/p&gt;

&lt;p&gt;Engineering time becomes support time.&lt;/p&gt;

&lt;p&gt;And support becomes &lt;strong&gt;unplanned work&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Another Case: When Third-Party Services Change
&lt;/h2&gt;

&lt;p&gt;We encountered a similar situation with &lt;strong&gt;Auth0&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A change in policy meant that a callback configuration required updates, including adding &lt;strong&gt;localhost to the allowed callback URLs&lt;/strong&gt; for certain flows.&lt;/p&gt;

&lt;p&gt;This change caused issues in the application, and it was reported as a bug.&lt;/p&gt;

&lt;p&gt;But the root cause wasn’t in our application code.&lt;/p&gt;

&lt;p&gt;It was a &lt;strong&gt;policy change from a third-party service&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So the question becomes:&lt;/p&gt;

&lt;p&gt;Should the development team fix this under the original project scope?&lt;/p&gt;

&lt;p&gt;Or should it be treated as &lt;strong&gt;ongoing platform maintenance&lt;/strong&gt;?&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Question: What Is Actually a Bug?
&lt;/h2&gt;

&lt;p&gt;This experience made me rethink something important.&lt;/p&gt;

&lt;p&gt;Not every issue reported in production is actually a &lt;strong&gt;software bug&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Some issues fall into other categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Infrastructure limitations&lt;/strong&gt;&lt;br&gt;
Example: Under-provisioned database resources.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Usage growth&lt;/strong&gt;&lt;br&gt;
Systems behaving differently as data and traffic scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Third-party service changes&lt;/strong&gt;&lt;br&gt;
Authentication providers, APIs, SDKs updating their policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Operational configuration issues&lt;/strong&gt;&lt;br&gt;
DNS, environment variables, callback URLs, quotas.&lt;/p&gt;

&lt;p&gt;Yet many organizations treat all of these as &lt;strong&gt;bugs that must be fixed immediately&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And engineers often jump in and solve them without questioning the &lt;strong&gt;long-term impact&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Larger Organizations Typically Do
&lt;/h2&gt;

&lt;p&gt;More mature software organizations usually separate work into clear categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Development Scope&lt;/strong&gt;&lt;br&gt;
Features agreed in the project contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Warranty Period&lt;/strong&gt;&lt;br&gt;
A limited period where genuine defects are fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Support / Maintenance Plan&lt;/strong&gt;&lt;br&gt;
Ongoing system maintenance, monitoring, infrastructure tuning, and external dependency updates.&lt;/p&gt;

&lt;p&gt;This ensures that engineering teams are not constantly pulled into &lt;strong&gt;unplanned work months after delivery&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons I Learned as an Engineer
&lt;/h2&gt;

&lt;p&gt;This experience taught me several lessons that go beyond debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Production Systems Are Living Systems
&lt;/h3&gt;

&lt;p&gt;They evolve as data, users, and dependencies change.&lt;/p&gt;

&lt;p&gt;Infrastructure decisions made early in a project may not hold months later.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Not Every Issue Is a Bug
&lt;/h3&gt;

&lt;p&gt;Sometimes the system is behaving exactly as expected.&lt;/p&gt;

&lt;p&gt;It’s the &lt;strong&gt;environment that changed&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Infrastructure Is Part of the Product
&lt;/h3&gt;

&lt;p&gt;Developers often think only about application code.&lt;/p&gt;

&lt;p&gt;But performance is frequently determined by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database tiers&lt;/li&gt;
&lt;li&gt;network limits&lt;/li&gt;
&lt;li&gt;cache strategies&lt;/li&gt;
&lt;li&gt;third-party APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ignoring infrastructure can lead to misleading conclusions about “bugs”.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. Fixed-Price Projects Need Clear Boundaries
&lt;/h3&gt;

&lt;p&gt;Without clear support agreements, teams risk entering a cycle of &lt;strong&gt;continuous unpaid maintenance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A sustainable approach usually includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;post-launch support plans&lt;/li&gt;
&lt;li&gt;infrastructure monitoring&lt;/li&gt;
&lt;li&gt;defined response scopes&lt;/li&gt;
&lt;li&gt;upgrade recommendations&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  5. Engineers Should Think Beyond Code
&lt;/h3&gt;

&lt;p&gt;One of the biggest mindset shifts for me was realizing that senior engineering roles require understanding not only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;systems&lt;/li&gt;
&lt;li&gt;debugging&lt;/li&gt;
&lt;li&gt;architecture&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;but also &lt;strong&gt;product sustainability and operational ownership&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The health of a system is not just technical.&lt;/p&gt;

&lt;p&gt;It’s also organizational.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;The original problem looked like a simple performance bug.&lt;/p&gt;

&lt;p&gt;But the deeper lesson had nothing to do with code.&lt;/p&gt;

&lt;p&gt;It was about understanding how &lt;strong&gt;software systems, infrastructure, business agreements, and third-party dependencies intersect&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As engineers, we often focus on fixing the problem in front of us.&lt;/p&gt;

&lt;p&gt;But sometimes the real challenge is asking a different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this actually a bug - or is this part of running a real production system?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the answer to that question can shape how a product - and a company - operates long term.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>backend</category>
      <category>devops</category>
      <category>startup</category>
    </item>
    <item>
      <title>What Working on Web Accessibility Taught Me (The Fun, the Frustration, and the Click)</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Thu, 05 Feb 2026 09:44:46 +0000</pubDate>
      <link>https://dev.to/sanket00123/what-working-on-web-accessibility-taught-me-the-fun-the-frustration-and-the-click-57ec</link>
      <guid>https://dev.to/sanket00123/what-working-on-web-accessibility-taught-me-the-fun-the-frustration-and-the-click-57ec</guid>
      <description>&lt;p&gt;Web accessibility is one of those things most of us &lt;em&gt;know&lt;/em&gt; is important - but don’t fully understand until we experience our own application from a completely different perspective.&lt;/p&gt;

&lt;p&gt;Recently, I spent time working on an accessibility-focused proof of concept where I audited and improved a web module using &lt;strong&gt;WCAG 2.1 AA guidelines&lt;/strong&gt;. What started as a technical exercise quickly became one of the most eye-opening development experiences I’ve had.&lt;/p&gt;

&lt;p&gt;It was fun.&lt;br&gt;&lt;br&gt;
It was frustrating.&lt;br&gt;&lt;br&gt;
And eventually - it &lt;em&gt;clicked&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I want to share what I learned while working through accessibility challenges and why it changed how I think about building web applications.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Why I Took an Accessibility-First Approach
&lt;/h2&gt;

&lt;p&gt;Accessibility is often treated as a final checklist item — something you verify before release. I wanted to try a different approach: treat accessibility as a &lt;strong&gt;non-negotiable constraint from the start&lt;/strong&gt;, similar to performance or security.&lt;/p&gt;

&lt;p&gt;Instead of just scanning for issues, I tried to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Audit UI components against WCAG guidelines&lt;/li&gt;
&lt;li&gt;Fix problems at the component and system level&lt;/li&gt;
&lt;li&gt;Verify fixes using real assistive technologies&lt;/li&gt;
&lt;li&gt;Avoid “ARIA band-aids” and focus on proper semantics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That shift alone changed how I approached UI development.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⌨️ The First Reality Check: Keyboard-Only Navigation
&lt;/h2&gt;

&lt;p&gt;The first thing I did was simple: I stopped using my mouse.&lt;/p&gt;

&lt;p&gt;And immediately, I started noticing problems.&lt;/p&gt;

&lt;p&gt;Things that felt completely fine visually became difficult to use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expandable rows that weren’t keyboard reachable
&lt;/li&gt;
&lt;li&gt;Buttons that had no visible focus state
&lt;/li&gt;
&lt;li&gt;Dialogs that opened but didn’t guide keyboard focus
&lt;/li&gt;
&lt;li&gt;UI flows that assumed users could see everything
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keyboard-only testing quickly exposes whether your UI is &lt;strong&gt;navigable&lt;/strong&gt;, not just visually functional.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔊 Screen Reader Testing: The Most Humbling Part
&lt;/h2&gt;

&lt;p&gt;I then tested the application using a screen reader (NVDA).&lt;/p&gt;

&lt;p&gt;That experience completely changed my perspective.&lt;/p&gt;

&lt;p&gt;Some common issues I discovered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Icon-only buttons announced as just &lt;em&gt;“button”&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Tables that lacked context or structure
&lt;/li&gt;
&lt;li&gt;Dynamic notifications that weren’t announced at all
&lt;/li&gt;
&lt;li&gt;Complex forms that were difficult to understand without visual grouping
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Technically, nothing was broken.&lt;br&gt;&lt;br&gt;
But the experience was exhausting and confusing.&lt;/p&gt;

&lt;p&gt;That’s when I realized:&lt;/p&gt;

&lt;p&gt;👉 Accessibility problems don’t always block users — they often just make tasks unnecessarily difficult.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Accessibility Issues Are Usually Systemic
&lt;/h2&gt;

&lt;p&gt;One of the biggest surprises during the audit was how many accessibility problems were &lt;strong&gt;repeated across components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Examples included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Icon buttons missing accessible names
&lt;/li&gt;
&lt;li&gt;Status messages not announced to assistive technologies
&lt;/li&gt;
&lt;li&gt;Missing focus management after dynamic UI changes
&lt;/li&gt;
&lt;li&gt;Animations ignoring reduced motion preferences
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These weren’t page-specific bugs.&lt;br&gt;&lt;br&gt;
They were &lt;strong&gt;component-level patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Fixing them once improved accessibility across multiple parts of the application.&lt;/p&gt;

&lt;p&gt;Accessibility isn’t just about screens — it’s about &lt;strong&gt;shared UI primitives&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 The Most Interesting Challenge: When a Table Isn’t Really a Table
&lt;/h2&gt;

&lt;p&gt;One interface I worked on visually resembled a table but behaved more like a dynamic form where users could add and edit rows.&lt;/p&gt;

&lt;p&gt;Initially, it used generic layout containers styled like a grid. Visually, it worked well. Semantically, it was confusing for assistive technologies.&lt;/p&gt;

&lt;p&gt;I had to step back and ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this data display or data entry?&lt;/li&gt;
&lt;li&gt;Should users navigate rows or form inputs?&lt;/li&gt;
&lt;li&gt;What interaction model best matches user expectations?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of forcing ARIA roles onto the layout, I switched to a more semantic structure using list and fieldset patterns. The visual design stayed the same, but the interaction became far clearer for screen readers and keyboard users.&lt;/p&gt;

&lt;p&gt;That experience reinforced an important lesson:&lt;/p&gt;

&lt;p&gt;👉 Accessibility is often solved through &lt;strong&gt;better structure&lt;/strong&gt;, not more attributes.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 How Accessibility Changes Your Development Mindset
&lt;/h2&gt;

&lt;p&gt;After working through accessibility improvements, I started noticing things I previously ignored:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where keyboard focus moves after actions
&lt;/li&gt;
&lt;li&gt;Whether UI updates are announced or silent
&lt;/li&gt;
&lt;li&gt;How clearly components communicate purpose
&lt;/li&gt;
&lt;li&gt;Whether interactions are predictable or surprising
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Accessibility forces you to think beyond visuals and focus on &lt;strong&gt;user experience flow&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Lessons I’m Taking Forward
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Accessibility Is Experiential
&lt;/h3&gt;

&lt;p&gt;Reading guidelines helps, but testing with real assistive tools reveals the actual user experience.&lt;/p&gt;




&lt;h3&gt;
  
  
  Most Accessibility Issues Aren’t Technically Complex
&lt;/h3&gt;

&lt;p&gt;They’re often small structural or semantic improvements that simply require awareness.&lt;/p&gt;




&lt;h3&gt;
  
  
  Design Decisions Matter More Than ARIA Fixes
&lt;/h3&gt;

&lt;p&gt;If the interaction model is wrong, ARIA rarely saves it. Starting with semantic HTML usually leads to better outcomes.&lt;/p&gt;




&lt;h3&gt;
  
  
  Accessibility Improves UX for Everyone
&lt;/h3&gt;

&lt;p&gt;Clear focus states, predictable navigation, and meaningful feedback benefit all users, not just those using assistive technologies.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏁 Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;Working on accessibility was genuinely fun — and occasionally frustrating in a productive way.&lt;/p&gt;

&lt;p&gt;Fun because solving these problems feels impactful.&lt;br&gt;&lt;br&gt;
Frustrating because it reveals how easily users can be excluded without anyone noticing.&lt;/p&gt;

&lt;p&gt;But once accessibility clicks, it becomes impossible to ignore.&lt;/p&gt;

&lt;p&gt;If you’ve never tried using your application without a mouse or with a screen reader, I highly recommend it. You’ll likely learn more in 30 minutes than from reading documentation alone.&lt;/p&gt;

&lt;p&gt;Here’s to building applications that work — &lt;strong&gt;for everyone&lt;/strong&gt; 🚀&lt;/p&gt;




</description>
      <category>a11y</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
    <item>
      <title>🚀 Building an AI-Powered Code Reviewer for Bitbucket Using Groq &amp; Pipelines</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Tue, 09 Dec 2025 12:54:46 +0000</pubDate>
      <link>https://dev.to/sanket00123/building-an-ai-powered-code-reviewer-for-bitbucket-using-groq-pipelines-2ah7</link>
      <guid>https://dev.to/sanket00123/building-an-ai-powered-code-reviewer-for-bitbucket-using-groq-pipelines-2ah7</guid>
      <description>&lt;p&gt;Modern development teams rely heavily on pull requests for code quality-but &lt;strong&gt;manual reviews are slow, inconsistent, and expensive&lt;/strong&gt;. Recently, Bitbucket introduced &lt;strong&gt;Rovo Dev&lt;/strong&gt;, and GitHub has &lt;strong&gt;Ask Copilot&lt;/strong&gt;, both offering AI-assisted PR reviews.&lt;/p&gt;

&lt;p&gt;But there was one major problem for me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ I wasn’t ready to pay &lt;strong&gt;$20 per developer per month&lt;/strong&gt; just to get AI reviews.&lt;br&gt;&lt;br&gt;
✅ I already had a &lt;strong&gt;Groq API key&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
✅ I wanted a &lt;strong&gt;fully automated, pipeline-driven solution&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I built my own &lt;strong&gt;AI-powered PR review system for Bitbucket&lt;/strong&gt; using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Bitbucket Pipelines&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Groq LLM (&lt;code&gt;llama-3.3-70b-versatile&lt;/code&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Git-based diff extraction (no REST API auth headaches)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This system reviews every PR automatically and outputs a &lt;strong&gt;structured, checklist-driven AI review&lt;/strong&gt;-with &lt;strong&gt;zero dependency on Bitbucket’s unreliable token ecosystem and zero per-developer licensing cost&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I’ll cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How this compares to &lt;strong&gt;Rovo Dev &amp;amp; GitHub Copilot&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Why I avoided Bitbucket’s REST APIs&lt;/li&gt;
&lt;li&gt;The final production architecture&lt;/li&gt;
&lt;li&gt;How the AI review works&lt;/li&gt;
&lt;li&gt;Key engineering lessons from building this&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🤖 Rovo Dev vs Ask Copilot vs This Approach
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Rovo Dev (Bitbucket)&lt;/th&gt;
&lt;th&gt;Ask Copilot (GitHub)&lt;/th&gt;
&lt;th&gt;This Groq-Based System&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI PR Reviews&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fully Automated in CI&lt;/td&gt;
&lt;td&gt;❌ (mostly UI based)&lt;/td&gt;
&lt;td&gt;❌ (manual prompts)&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Per-Developer Cost&lt;/td&gt;
&lt;td&gt;❌ $20/month/dev&lt;/td&gt;
&lt;td&gt;❌ Bundled with Copilot&lt;/td&gt;
&lt;td&gt;✅ &lt;strong&gt;$0 per dev&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Works in Pipelines&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Review Rules&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;❌ Limited&lt;/td&gt;
&lt;td&gt;✅ Full control&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vendor Lock-in&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;❌ None (Groq + Git)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I didn’t want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Another &lt;strong&gt;per-seat SaaS subscription&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;manual “Ask AI” workflow&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Or a system that breaks when pricing changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wanted:&lt;br&gt;
✅ Fully automated&lt;br&gt;&lt;br&gt;
✅ CI-level enforcement&lt;br&gt;&lt;br&gt;
✅ Custom review rules&lt;br&gt;&lt;br&gt;
✅ Lowest possible cost  &lt;/p&gt;

&lt;p&gt;That’s why I chose &lt;strong&gt;Groq + Pipelines&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  ❌ The Problem with Traditional Bitbucket PR Automation
&lt;/h2&gt;

&lt;p&gt;Initially, I tried the standard approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch PR diffs using the &lt;strong&gt;Bitbucket REST API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Post PR comments using:

&lt;ul&gt;
&lt;li&gt;Atlassian API tokens&lt;/li&gt;
&lt;li&gt;Workspace tokens&lt;/li&gt;
&lt;li&gt;Repository access tokens&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite correct scopes, &lt;strong&gt;PR comment posting repeatedly failed with &lt;code&gt;401 Unauthorized&lt;/code&gt; errors&lt;/strong&gt; due to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inconsistent token behaviors&lt;/li&gt;
&lt;li&gt;Bitbucket’s evolving security model&lt;/li&gt;
&lt;li&gt;Poor documentation around 2025 token behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After continous debugging, I realized:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;The smartest move was to eliminate Bitbucket’s REST API entirely for diff collection.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  ✅ The Final Working Architecture
&lt;/h2&gt;

&lt;p&gt;Here’s the &lt;strong&gt;production setup that actually works&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;Pull Request Created&lt;br&gt;
         ↓&lt;br&gt;
Bitbucket Pipeline Triggered&lt;br&gt;
         ↓&lt;br&gt;
Git diff extracted using: git diff origin/main...HEAD&lt;br&gt;
         ↓&lt;br&gt;
Diff sent to Groq LLM&lt;br&gt;
         ↓&lt;br&gt;
AI generates structured checklist-based review&lt;br&gt;
         ↓&lt;br&gt;
Review shown in Pipeline logs + downloadable artifact&lt;/p&gt;
&lt;h3&gt;
  
  
  Why this works so well:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ No REST API calls for diffs&lt;/li&gt;
&lt;li&gt;✅ No authentication failures&lt;/li&gt;
&lt;li&gt;✅ No permission issues&lt;/li&gt;
&lt;li&gt;✅ No flakiness&lt;/li&gt;
&lt;li&gt;✅ Fully deterministic&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🤖 The AI Review Rules (Enterprise-Grade)
&lt;/h2&gt;

&lt;p&gt;The AI review is driven by a &lt;strong&gt;strict TypeScript + Angular + security checklist&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;❌ No &lt;code&gt;any&lt;/code&gt; types&lt;/li&gt;
&lt;li&gt;✅ Strong typing with interfaces &amp;amp; generics&lt;/li&gt;
&lt;li&gt;✅ Modern Angular syntax (&lt;code&gt;@if&lt;/code&gt;, &lt;code&gt;@for&lt;/code&gt;, standalone components)&lt;/li&gt;
&lt;li&gt;✅ Authentication guards&lt;/li&gt;
&lt;li&gt;✅ No hardcoded secrets&lt;/li&gt;
&lt;li&gt;✅ Error handling&lt;/li&gt;
&lt;li&gt;✅ Tests present&lt;/li&gt;
&lt;li&gt;✅ Performance checks&lt;/li&gt;
&lt;li&gt;✅ Accessibility (WCAG)&lt;/li&gt;
&lt;li&gt;✅ Final verdict: &lt;strong&gt;MERGE READY / NEEDS WORK&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Consistent reviews&lt;/li&gt;
&lt;li&gt;Enforced standards&lt;/li&gt;
&lt;li&gt;Zero reviewer bias&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  🧠 Git-Based Diff Instead of REST API
&lt;/h2&gt;

&lt;p&gt;Instead of calling Bitbucket’s REST endpoints, the pipeline simply runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git fetch origin main
git diff origin/main...HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives:&lt;/p&gt;

&lt;p&gt;✅ The exact PR diff&lt;/p&gt;

&lt;p&gt;✅ No API authentication&lt;/p&gt;

&lt;p&gt;✅ Works in every CI environment&lt;/p&gt;

&lt;p&gt;This single decision eliminated 90% of the system’s complexity.&lt;/p&gt;

&lt;p&gt;⚡ Groq LLM Integration&lt;br&gt;
The diff is sent to Groq using:&lt;br&gt;
llama-3.3-70b-versatile&lt;/p&gt;

&lt;p&gt;Why Groq?&lt;br&gt;
⚡ Extremely fast inference&lt;/p&gt;

&lt;p&gt;🧠 Excellent reasoning on large diffs&lt;/p&gt;

&lt;p&gt;💸 Much cheaper than many alternatives&lt;/p&gt;

&lt;p&gt;✅ OpenAI-compatible API&lt;/p&gt;

&lt;p&gt;🌱 More eco-friendly due to lower compute time per request&lt;/p&gt;

&lt;p&gt;The AI responds with:&lt;/p&gt;

&lt;p&gt;🚨 Critical Issues&lt;/p&gt;

&lt;p&gt;🔒 Security Analysis&lt;/p&gt;

&lt;p&gt;⚡ Performance Review&lt;/p&gt;

&lt;p&gt;🏗️ Architecture Feedback&lt;/p&gt;

&lt;p&gt;📝 Maintainability&lt;/p&gt;

&lt;p&gt;✅ Final Verdict: MERGE READY / NEEDS WORK&lt;/p&gt;

&lt;p&gt;📄 Where the AI Review Appears Instead of battling PR comment permissions:&lt;/p&gt;

&lt;p&gt;✅ The full AI review appears in the Pipelines logs&lt;/p&gt;

&lt;p&gt;✅ Optionally saved as a downloadable ai-review.md artifact&lt;/p&gt;

&lt;p&gt;✅ No PR write permissions required&lt;/p&gt;

&lt;p&gt;✅ No security risks&lt;/p&gt;

&lt;p&gt;This turned out to be far more enterprise-compliant than auto-commenting.&lt;/p&gt;

&lt;p&gt;🧪 Production Impact After enabling this system:&lt;/p&gt;

&lt;p&gt;✅ Every PR is reviewed automatically&lt;/p&gt;

&lt;p&gt;✅ Developers get feedback in minutes&lt;/p&gt;

&lt;p&gt;✅ Review standards are enforced consistently&lt;/p&gt;

&lt;p&gt;✅ Human reviewers focus only on business logic&lt;/p&gt;

&lt;p&gt;✅ No failed pipelines due to auth issues&lt;/p&gt;

&lt;p&gt;✅ No wasted build minutes on retries&lt;/p&gt;

&lt;p&gt;✅ Zero per-developer licensing cost&lt;/p&gt;

&lt;p&gt;🔑 Key Engineering Lessons&lt;br&gt;
Avoid brittle platform APIs when Git can do the job&lt;/p&gt;

&lt;p&gt;AI reviewers should assist, not block developers&lt;/p&gt;

&lt;p&gt;PR comments are optional-reviews must be reliable&lt;/p&gt;

&lt;p&gt;Pipelines + Git + LLM = extremely powerful combination&lt;/p&gt;

&lt;p&gt;Groq is ideal for CI/CD AI workloads&lt;/p&gt;

&lt;p&gt;Not every AI solution needs a $20/month/dev license&lt;/p&gt;

&lt;p&gt;📌 What’s Next?&lt;br&gt;
Planned upgrades:&lt;/p&gt;

&lt;p&gt;✅ Auto-block merge when verdict = NEEDS WORK&lt;/p&gt;

&lt;p&gt;✅ Language-specific reviewers (.NET, SQL)&lt;/p&gt;

&lt;p&gt;✅ Security-only review mode&lt;/p&gt;

&lt;p&gt;✅ Architectural drift detection&lt;/p&gt;

&lt;p&gt;✅ Final Thoughts&lt;br&gt;
If you're using Bitbucket and want reliable AI-powered PR reviews without paying enterprise per-seat pricing, my recommendation is:&lt;/p&gt;

&lt;p&gt;💡 Use Git for diff extraction + Groq for AI analysis + Pipelines for automation. Avoid REST API auth wherever possible.&lt;/p&gt;

&lt;p&gt;It’s simpler. It’s faster. It’s cheaper. And it actually works in production.&lt;/p&gt;

</description>
      <category>bitbucket</category>
      <category>ai</category>
      <category>codereview</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Building an Auto-Logout System for Angular Applications: Securing User Sessions with Inactivity Detection</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Fri, 31 Oct 2025 11:20:33 +0000</pubDate>
      <link>https://dev.to/sanket00123/building-an-auto-logout-system-for-angular-applications-securing-user-sessions-with-inactivity-1oj</link>
      <guid>https://dev.to/sanket00123/building-an-auto-logout-system-for-angular-applications-securing-user-sessions-with-inactivity-1oj</guid>
      <description>&lt;h2&gt;
  
  
  🧠 Introduction
&lt;/h2&gt;

&lt;p&gt;In modern web applications, security extends far beyond authentication - it’s also about protecting &lt;strong&gt;active user sessions&lt;/strong&gt; from unauthorized access.  &lt;/p&gt;

&lt;p&gt;One often-overlooked feature in this area is &lt;strong&gt;automatic logout due to inactivity&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Imagine a user leaving a laptop unlocked with sensitive data on-screen. Without an inactivity timeout, that session remains vulnerable.&lt;/p&gt;

&lt;p&gt;In this post, we’ll walk through how to implement a &lt;strong&gt;robust auto-logout mechanism in Angular&lt;/strong&gt; that detects user inactivity, displays a warning dialog, and safely logs the user out after a configurable timeout period.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚨 The Problem
&lt;/h2&gt;

&lt;p&gt;Enterprise and data-sensitive applications often need to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically terminate sessions after inactivity
&lt;/li&gt;
&lt;li&gt;Display a warning before logout
&lt;/li&gt;
&lt;li&gt;Detect real user activity (not just page loads)
&lt;/li&gt;
&lt;li&gt;Prevent memory leaks via proper cleanup
&lt;/li&gt;
&lt;li&gt;Maintain a smooth, non-intrusive user experience
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 The Solution: InactivityService
&lt;/h2&gt;

&lt;p&gt;We’ll build an &lt;code&gt;InactivityService&lt;/code&gt; that can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Detect inactivity using multiple event types
&lt;/li&gt;
&lt;li&gt;Display a configurable warning dialog
&lt;/li&gt;
&lt;li&gt;Auto-logout after a timeout
&lt;/li&gt;
&lt;li&gt;Clean up resources properly
&lt;/li&gt;
&lt;li&gt;Work seamlessly with Angular change detection
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚙️ Step 1: Service Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;InactivityService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;INACTIVITY_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 1 hour&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;WARNING_TIME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 5 minutes&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;lastActivityTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;inactivityTimer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;warningTimer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;isWarningShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;isTracking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;activityEvents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousedown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keypress&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;touchstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NgZone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Design Choices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multiple event types:&lt;/strong&gt; Tracks various forms of user input.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NgZone usage:&lt;/strong&gt; Ensures Angular detects UI updates correctly.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State flags:&lt;/strong&gt; Manage active state and prevent duplicate warnings.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🖱️ Step 2: Tracking User Activity
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;startTracking&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetTimer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addActivityListeners&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;addActivityListeners&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activityEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;passive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;onActivity&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ngZone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetActivity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;resetActivity&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastActivityTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isWarningShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetTimer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Matters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;passive: true&lt;/code&gt; improves scroll performance.
&lt;/li&gt;
&lt;li&gt;Capturing phase ensures early event detection.
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NgZone.run()&lt;/code&gt; allows Angular to refresh bindings if needed.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⏰ Step 3: Timer Management
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;resetTimer&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearTimers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Warning before logout&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warningTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showInactivityWarning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INACTIVITY_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WARNING_TIME&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Auto-logout&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inactivityTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;performLogout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INACTIVITY_TIMEOUT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;clearTimers&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inactivityTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inactivityTimer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warningTimer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warningTimer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inactivityTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;warningTimer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Timer Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate timers for &lt;strong&gt;warning&lt;/strong&gt; and &lt;strong&gt;logout&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Reset on any detected activity.
&lt;/li&gt;
&lt;li&gt;Clear all on logout to prevent memory leaks.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ Step 4: Displaying the Warning Dialog
&lt;/h2&gt;

&lt;p&gt;We’ll create a minimal dialog using &lt;strong&gt;vanilla JavaScript&lt;/strong&gt; to avoid external dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;showInactivityWarning&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isWarningShown&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;existing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inactivity-warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isWarningShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overlay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inactivity-warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rgba(0,0,0,0.4)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;flex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;alignItems&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;justifyContent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;zIndex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;9999&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dialog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#fff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;24px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;borderRadius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;8px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;textAlign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;center&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;boxShadow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0 4px 10px rgba(0,0,0,0.3)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;300px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;h3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Session Timeout Warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;p&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;You will be logged out in 5 minutes due to inactivity.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stayBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;stayBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Stay Logged In&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;stayBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dismissWarning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resetActivity&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logoutBtn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;logoutBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Logout Now&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;logoutBtn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onclick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dismissWarning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;performLogout&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stayBtn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;logoutBtn&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dialog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overlay&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;dismissWarning&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;warning&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inactivity-warning&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isWarningShown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advantages of This Approach
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Zero external dependencies
&lt;/li&gt;
&lt;li&gt;Works even if Angular rendering pauses
&lt;/li&gt;
&lt;li&gt;Customizable look and feel
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🚪 Step 5: Performing Logout
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;performLogout&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopTracking&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dismissWarning&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Clear any cached data&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Redirect to login or home page&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;stopTracking&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTracking&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearTimers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activityEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onActivity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🔗 Integration in Your Angular App
&lt;/h2&gt;

&lt;p&gt;To enable inactivity tracking globally, start the service in your main &lt;code&gt;AppComponent&lt;/code&gt; or after user login:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AppComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;inactivityService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InactivityService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;inactivityService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startTracking&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Inactivity tracking enabled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧭 Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Configurable Timeouts
&lt;/h3&gt;

&lt;p&gt;Use environment variables or role-based settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;INACTIVITY_TIMEOUT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 15 minutes for admins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Server-Side Session Expiry
&lt;/h3&gt;

&lt;p&gt;Don’t rely solely on client logic-implement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Short-lived JWTs
&lt;/li&gt;
&lt;li&gt;Refresh token rotation
&lt;/li&gt;
&lt;li&gt;Server-side session validation
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. UX &amp;amp; Accessibility
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Provide clear messages
&lt;/li&gt;
&lt;li&gt;Allow time to respond
&lt;/li&gt;
&lt;li&gt;Add ARIA attributes for screen readers
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Performance
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;passive: true&lt;/code&gt; listeners
&lt;/li&gt;
&lt;li&gt;Debounce high-frequency events if needed
&lt;/li&gt;
&lt;li&gt;Clean up listeners on component destroy
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Testing Tips
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Simulate user inactivity with fake timers
&lt;/li&gt;
&lt;li&gt;Verify that warning appears before logout
&lt;/li&gt;
&lt;li&gt;Ensure timers reset on user activity
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example test snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should reset activity on user interaction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startTracking&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dispatchEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MouseEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mousemove&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lastActivityTime&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;toBeGreaterThan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  💡 Real-World Benefits
&lt;/h2&gt;

&lt;p&gt;Implementing inactivity logout helps you achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔒 &lt;strong&gt;Improved session security&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Compliance&lt;/strong&gt; with standards like HIPAA / GDPR
&lt;/li&gt;
&lt;li&gt;💬 &lt;strong&gt;User trust&lt;/strong&gt; through clear timeout warnings
&lt;/li&gt;
&lt;li&gt;🧹 &lt;strong&gt;Cleaner memory management&lt;/strong&gt; via proper event cleanup
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;Building an auto-logout system may seem small, but it significantly boosts your application’s &lt;strong&gt;security posture&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;This approach offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Comprehensive user activity detection
&lt;/li&gt;
&lt;li&gt;Configurable timeout and warning
&lt;/li&gt;
&lt;li&gt;Lightweight implementation with no dependencies
&lt;/li&gt;
&lt;li&gt;Full Angular compatibility
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Secure, user-friendly, and easy to integrate - this solution protects both your users and your platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://angular.io/guide/zone" rel="noopener noreferrer"&gt;Angular Zones Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener" rel="noopener noreferrer"&gt;MDN: addEventListener()&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html" rel="noopener noreferrer"&gt;OWASP Session Management Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Discussion
&lt;/h2&gt;

&lt;p&gt;What session timeout strategies do you use in your applications?&lt;br&gt;&lt;br&gt;
Let’s exchange ideas below 👇&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building a Production-Ready Logger Service in Angular 🚀</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Tue, 30 Sep 2025 08:24:12 +0000</pubDate>
      <link>https://dev.to/sanket00123/building-a-production-ready-logger-service-in-angular-cc8</link>
      <guid>https://dev.to/sanket00123/building-a-production-ready-logger-service-in-angular-cc8</guid>
      <description>&lt;p&gt;When I started working on Angular app, I noticed one common thing: &lt;strong&gt;console.log everywhere&lt;/strong&gt;. Debug messages scattered across components, warnings mixed with production logs, and the occasional sensitive info sneaking into the console.&lt;/p&gt;

&lt;p&gt;With guidance from my peers, I learned about a much better approach-&lt;strong&gt;a centralized Logger Service&lt;/strong&gt;. In this post, I’ll walk you through a &lt;strong&gt;production-ready Logger Service implementation&lt;/strong&gt; for Angular that makes logging clean, powerful, and safe.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem 🤔
&lt;/h2&gt;

&lt;p&gt;We’ve all been there-debugging with &lt;code&gt;console.log()&lt;/code&gt; sprinkled across the codebase.&lt;br&gt;
The issues?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cluttered production logs&lt;/li&gt;
&lt;li&gt;Manual cleanup before deployment&lt;/li&gt;
&lt;li&gt;Inconsistent formatting&lt;/li&gt;
&lt;li&gt;No central control&lt;/li&gt;
&lt;li&gt;Potential exposure of sensitive info&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Solution ✨
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Logger Service&lt;/strong&gt; that provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Environment-aware logging (disabled in production)&lt;/li&gt;
&lt;li&gt;✅ Multiple log levels: DEBUG, INFO, WARN, ERROR&lt;/li&gt;
&lt;li&gt;✅ Consistent formatting with timestamps&lt;/li&gt;
&lt;li&gt;✅ Advanced features (grouping, timing, styled logs, tables)&lt;/li&gt;
&lt;li&gt;✅ Type safety with full TypeScript support&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Implementation 💻
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Core Logger Service
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;DEBUG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;INFO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;WARN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;ERROR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LoggerService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;production&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;enableLogging&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;enableLogging&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hasOwnProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;logLevel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WARN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;level&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;] [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;]`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WARN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;ERROR&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Key highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Disabled automatically in production&lt;/li&gt;
&lt;li&gt;Errors always logged regardless of environment&lt;/li&gt;
&lt;li&gt;ISO timestamps for precise log tracking&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Advanced Features 🎯
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Grouping Related Logs
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;collapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;collapsed&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupCollapsed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupEnd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Performance Timing
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  3. Table Display
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  4. Styled Logs
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color: #2196F3; font-weight: bold;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEnabled&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logLevel&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`%c&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Migration Guide 📝
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Debug info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Warning message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error occurred&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;After:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Debug info&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Warning message&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Error occurred&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Dynamic Configuration ⚙️
&lt;/h2&gt;

&lt;p&gt;Enable/disable logging at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoggerService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;debug=true&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setEnabled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLogLevel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DEBUG&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Benefits 🎁
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Cleaner production logs&lt;/li&gt;
&lt;li&gt;Rich formatting and timestamps&lt;/li&gt;
&lt;li&gt;Toggle logging with a single flag&lt;/li&gt;
&lt;li&gt;Zero overhead when disabled&lt;/li&gt;
&lt;li&gt;Type safety with TypeScript&lt;/li&gt;
&lt;li&gt;Consistent across the app&lt;/li&gt;
&lt;li&gt;No accidental leakage of sensitive info&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Best Practices 📚
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;logger.error()&lt;/code&gt; for errors (always logged)&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;debug()&lt;/code&gt; for diagnostics, &lt;code&gt;info()&lt;/code&gt; for general messages, &lt;code&gt;warn()&lt;/code&gt; for potential issues&lt;/li&gt;
&lt;li&gt;Group related logs for readability&lt;/li&gt;
&lt;li&gt;Time performance-critical operations&lt;/li&gt;
&lt;li&gt;Replace all &lt;code&gt;console.&lt;/code&gt; with &lt;code&gt;logger.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;A &lt;strong&gt;Logger Service&lt;/strong&gt; is one of those simple but powerful upgrades that every Angular app should have.&lt;br&gt;
It makes logs consistent, keeps production clean, and gives developers richer debugging tools.&lt;/p&gt;

&lt;p&gt;Since adding it to our project, debugging has become easier and our production logs are finally clean.&lt;br&gt;
No more scattered &lt;code&gt;console.logs&lt;/code&gt; 🚫&lt;/p&gt;




&lt;p&gt;💬 What’s your logging strategy? Share your approach in the comments!&lt;/p&gt;

</description>
      <category>angular</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>cleancode</category>
    </item>
    <item>
      <title>Angular Architecture That Clicks: Embracing Feature-Based Design</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Thu, 21 Aug 2025 05:03:05 +0000</pubDate>
      <link>https://dev.to/sanket00123/angular-architecture-that-clicks-embracing-feature-based-design-4eje</link>
      <guid>https://dev.to/sanket00123/angular-architecture-that-clicks-embracing-feature-based-design-4eje</guid>
      <description>&lt;p&gt;Structuring an Angular app may seem straightforward at first-just put components in one folder, services in another, and models in their own. But as projects grow, that neat separation can quickly turn into a maze of files.&lt;/p&gt;

&lt;p&gt;Reflecting on a recent project, I realized how much time I wasted bouncing between folders just to make a small change in one feature. That’s when I decided to shift from the &lt;strong&gt;type-based structure&lt;/strong&gt; to a &lt;strong&gt;feature-based design&lt;/strong&gt;-and it completely changed how I build and maintain Angular apps.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through why this shift clicked for me, the challenges it solved, and how it makes apps more modular and scalable.&lt;/p&gt;




&lt;p&gt;🛠️ Challenges with Type-Based Structure&lt;br&gt;
At first, the default structure looked clean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/components  
/services  
/models  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But real-world development quickly exposed its flaws:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scattered Logic&lt;/strong&gt;: Updating a single feature meant editing files across multiple folders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding Pain&lt;/strong&gt;: New developers struggled to trace what belonged to which feature.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scaling Issues&lt;/strong&gt;: As features grew, so did the complexity of managing cross-folder dependencies.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🔄 The Shift to Feature-Based Design&lt;br&gt;
Instead of grouping files by type, I started grouping them by feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/features  
   /dashboard  
      dashboard.component.ts  
      dashboard.service.ts  
      dashboard.module.ts  
   /user  
      user.component.ts  
      user.service.ts  
      user.model.ts  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything related to “User” now lives in one place. Need to update user logic? It’s all inside &lt;code&gt;/user&lt;/code&gt;. Want to add a new feature? Create a new folder and keep it self-contained.&lt;/p&gt;




&lt;p&gt;🚀 Benefits I Experienced&lt;br&gt;
The difference was immediate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt; → Features became self-contained, easier to maintain, and simpler to test.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; → Features could be lazy-loaded, reducing initial bundle size.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt; → Teams could work on different features in parallel with minimal conflicts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clarity&lt;/strong&gt; → The structure told a story. Even new developers instantly knew where to look.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;📖 Lessons Learned&lt;br&gt;
Making the switch taught me a few key lessons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Align with Angular’s Strengths&lt;/strong&gt;: Angular is inherently module-driven, so a feature-based structure plays to its strengths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Think in Features, Not Files&lt;/strong&gt;: Real-world applications evolve around features, not isolated file types.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refactor Early&lt;/strong&gt;: The earlier you move to feature-based design, the less painful the transition.&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;🏁 Conclusion&lt;br&gt;
Shifting to feature-based design wasn’t just a structural change-it was a mindset shift. By organizing code around features instead of file types, I cut down development time, reduced confusion, and made the codebase far more modular.&lt;/p&gt;

&lt;p&gt;If you’re still working with a type-based Angular structure, I encourage you to try the feature-based approach. Like me, you might find it just &lt;em&gt;clicks&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s to building modular, scalable, and developer-friendly Angular apps 🚀&lt;/p&gt;

</description>
      <category>angular</category>
      <category>designpatterns</category>
      <category>webdev</category>
      <category>typescript</category>
    </item>
    <item>
      <title>From Basics to Battle-Tested: 10 Tech Foundations You Should Actually Master</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Tue, 27 May 2025 07:29:36 +0000</pubDate>
      <link>https://dev.to/sanket00123/from-basics-to-battle-tested-10-tech-foundations-you-should-actually-master-d9i</link>
      <guid>https://dev.to/sanket00123/from-basics-to-battle-tested-10-tech-foundations-you-should-actually-master-d9i</guid>
      <description>&lt;p&gt;The tech industry moves fast, but solid foundations move with you.&lt;/p&gt;

&lt;p&gt;Whether you're building cloud-native apps, running production-grade infrastructure, or automating deployments - there’s a &lt;strong&gt;huge difference&lt;/strong&gt; between knowing the &lt;em&gt;commands&lt;/em&gt; and understanding the &lt;em&gt;systems&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Here’s a curated list of &lt;strong&gt;10 core areas&lt;/strong&gt; you should master, along with the &lt;em&gt;why&lt;/em&gt; behind them.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. 🐧 Linux + Networking
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write robust Bash scripts with error handling and signal traps&lt;/li&gt;
&lt;li&gt;Understand TCP/IP, subnets, MTU, and DNS resolution&lt;/li&gt;
&lt;li&gt;Dive into &lt;code&gt;iptables&lt;/code&gt;, not just cloud firewall rules&lt;/li&gt;
&lt;li&gt;Use tools like &lt;code&gt;tcpdump&lt;/code&gt; and &lt;code&gt;wireshark&lt;/code&gt; to trace packets&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 If your app is slow or unreachable, networking fundamentals usually have the answer.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. 🐳 Docker
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;multi-stage builds&lt;/strong&gt; to keep images clean&lt;/li&gt;
&lt;li&gt;Integrate &lt;strong&gt;Trivy&lt;/strong&gt; for vulnerability scanning in CI&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;minimal base images&lt;/strong&gt; like &lt;code&gt;alpine&lt;/code&gt; or &lt;code&gt;distroless&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔐 Smaller, more secure containers = faster and safer deploys.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. 🧠 Git (Not Just the Commands)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use feature branch workflows with clean merges&lt;/li&gt;
&lt;li&gt;Make &lt;strong&gt;atomic commits&lt;/strong&gt; with meaningful messages&lt;/li&gt;
&lt;li&gt;Understand Git's &lt;strong&gt;DAG&lt;/strong&gt; structure (Directed Acyclic Graph)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🧬 Git history is your project's DNA. Learn to shape it cleanly.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. ☁️ Cloud Platform (Pick One - Azure in this case)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design &lt;strong&gt;VNet architectures&lt;/strong&gt; with private endpoints, service endpoints, and routing&lt;/li&gt;
&lt;li&gt;Apply &lt;strong&gt;RBAC&lt;/strong&gt; and &lt;strong&gt;Azure AD roles&lt;/strong&gt; with least privilege&lt;/li&gt;
&lt;li&gt;Enforce &lt;strong&gt;policy-based guardrails&lt;/strong&gt; using Azure Policy and Blueprints&lt;/li&gt;
&lt;li&gt;Optimize cost with &lt;strong&gt;resource tagging&lt;/strong&gt; and &lt;strong&gt;Azure Cost Management&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;☁️ Cloud mastery = security, cost control, and scalability.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5. 🔧 Terraform
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manage &lt;strong&gt;state&lt;/strong&gt; responsibly (remote backend, locking, state drift detection)&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;modular design&lt;/strong&gt; to scale Terraform across environments&lt;/li&gt;
&lt;li&gt;Add &lt;strong&gt;validators&lt;/strong&gt; with &lt;code&gt;validation&lt;/code&gt; blocks and use &lt;code&gt;tflint&lt;/code&gt; in CI&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🧱 Infra as Code isn't just writing resources-it's about reusability and governance.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. 🔁 CI/CD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Design &lt;strong&gt;stateless, idempotent pipelines&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;multi-environment promotion&lt;/strong&gt; (e.g., Dev → QA → Prod) with approvals&lt;/li&gt;
&lt;li&gt;Manage secrets with &lt;strong&gt;Azure Key Vault&lt;/strong&gt; or HashiCorp Vault&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🚀 A broken pipeline breaks your ability to deliver. Build it right from the start.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  7. 🐍 Python for Automation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write automation scripts with structured logging and exception handling&lt;/li&gt;
&lt;li&gt;Use retry/backoff patterns when calling APIs&lt;/li&gt;
&lt;li&gt;Build infrastructure tests with &lt;code&gt;pytest&lt;/code&gt;, &lt;code&gt;moto&lt;/code&gt;, or &lt;code&gt;localstack&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🤖 Python is your best friend for scripting and automation-write like it’s going to prod.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. 🧭 Azure + GitOps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;strong&gt;Bicep&lt;/strong&gt; or &lt;strong&gt;ARM templates&lt;/strong&gt; to define infrastructure declaratively&lt;/li&gt;
&lt;li&gt;Deploy infra using &lt;strong&gt;Azure DevOps Pipelines&lt;/strong&gt; or &lt;strong&gt;GitHub Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Implement GitOps with &lt;strong&gt;Azure Arc&lt;/strong&gt; or &lt;strong&gt;FluxCD&lt;/strong&gt; on AKS&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Policy as Code&lt;/strong&gt; and custom &lt;strong&gt;Azure Policy Definitions&lt;/strong&gt; for compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;☁️ GitOps isn’t just for Kubernetes - it's a philosophy you can apply to ARM/Bicep and everything Azure-native.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  9. 📊 Logging + Monitoring
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Centralize &lt;strong&gt;logs, metrics, and traces&lt;/strong&gt; using Azure Monitor and Application Insights&lt;/li&gt;
&lt;li&gt;Create &lt;strong&gt;SLO-based alerts&lt;/strong&gt;, not just static thresholds&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;distributed tracing&lt;/strong&gt; for microservices via OpenTelemetry&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;👁️ Observability isn’t optional. It's how you see into your systems and respond fast.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  10. 🔐 Security (Shift Left)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;What to know:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;Trivy&lt;/code&gt;, &lt;code&gt;Checkov&lt;/code&gt;, and &lt;code&gt;Defender for Cloud&lt;/code&gt; for early vulnerability scanning&lt;/li&gt;
&lt;li&gt;Validate compliance using &lt;strong&gt;Azure Policy&lt;/strong&gt; and &lt;strong&gt;Security Center&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Build &lt;strong&gt;immutable infrastructure&lt;/strong&gt; - no SSH, no patching in prod&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🔐 Secure infrastructure is built, not bolted on later.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Final Thought 💬
&lt;/h2&gt;

&lt;p&gt;This isn't about tools-it's about understanding &lt;strong&gt;how systems work&lt;/strong&gt; and how to build for failure, scale, and security. Don’t just memorize flags. Learn the concepts.&lt;/p&gt;

&lt;p&gt;📌 &lt;strong&gt;Pick one area. Go deep. Then level up the next.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;🙏 If this was useful, drop a ❤️ or follow for future deep dives on DevOps, automation, and infrastructure engineering.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cloud</category>
      <category>linux</category>
      <category>git</category>
    </item>
    <item>
      <title>Mastering Data Integration with Azure Data Factory</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Mon, 24 Feb 2025 08:14:01 +0000</pubDate>
      <link>https://dev.to/sanket00123/mastering-data-integration-with-azure-data-factory-57lc</link>
      <guid>https://dev.to/sanket00123/mastering-data-integration-with-azure-data-factory-57lc</guid>
      <description>&lt;p&gt;Data integration is at the heart of building scalable and efficient systems. Whether you're dealing with large datasets, ensuring referential integrity, or optimizing execution flows, having a structured approach is essential. In this blog, we'll walk through the key aspects of data integration using Azure Data Factory (ADF), covering pipeline execution, data flows, foreign key relationships, and optimization strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data Integration Pipelines
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Data Ingestion and Transformation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Copy Data Activity
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Source:&lt;/strong&gt; A view containing structured data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sink:&lt;/strong&gt; Destination table for processed data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Write Behavior:&lt;/strong&gt; Upsert for handling updates efficiently&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Primary Key Handling:&lt;/strong&gt; Ensuring uniqueness for seamless integration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Insert Optimization:&lt;/strong&gt; Enabled for performance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Schema Mapping:&lt;/strong&gt; Importing schema, removing unwanted columns, and aligning similar fields&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pre-Copy Script:&lt;/strong&gt; Handling identity inserts dynamically&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Stored Procedure for Cleanup
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stored Procedure Execution:&lt;/strong&gt; Ensures obsolete records are flagged for deletion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Soft deletes records not present in the source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execution Context:&lt;/strong&gt; Runs within a defined integration service&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Managing Dependencies in Pipelines
&lt;/h2&gt;

&lt;p&gt;For a successful data flow, foreign key relationships must be respected. Pipelines execute in a structured order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Entity A&lt;/strong&gt; (No dependencies)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entity B&lt;/strong&gt; (Reference to Entity A)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entity C&lt;/strong&gt; (Reference to Entity A &amp;amp; B)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Entity D&lt;/strong&gt; (Multiple foreign key dependencies)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This execution order prevents constraint violations and maintains data integrity.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Series Execution Pipeline
&lt;/h2&gt;

&lt;p&gt;A dedicated execution pipeline coordinates all pipelines sequentially:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures execution in the correct order&lt;/li&gt;
&lt;li&gt;Prevents independent triggers from causing conflicts&lt;/li&gt;
&lt;li&gt;Uses failure handling to halt execution for debugging&lt;/li&gt;
&lt;li&gt;Scheduled to run at predefined intervals for consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Handling Complex Scenarios
&lt;/h2&gt;

&lt;p&gt;Some datasets require additional filtering to prevent duplication and ensure integrity. Consider an example where a hierarchical structure exists (e.g., parent-child relationships). The following SQL logic ensures parent records exist before inserting child records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;SourceTable&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;TargetTable&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; 
&lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParentID&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;OR&lt;/span&gt; &lt;span class="k"&gt;EXISTS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;TargetTable&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParentID&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents foreign key constraint violations, ensuring smooth execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Monitoring &amp;amp; Troubleshooting
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Failure Handling:&lt;/strong&gt; The pipeline stops execution when errors occur, simplifying debugging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Soft Deletes:&lt;/strong&gt; Keeps track of obsolete records while preserving data integrity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Centralized Monitoring:&lt;/strong&gt; A single point of execution improves traceability and performance tracking.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Data integration isn't just about moving data—it's about maintaining consistency, ensuring referential integrity, and optimizing execution. A structured approach like the one outlined above enables seamless integration, reducing failures and improving maintainability. Whether you're building from scratch or refining an existing system, these best practices will help you navigate the complexities of data pipelines.&lt;/p&gt;

&lt;p&gt;Have you encountered challenges while implementing data pipelines? Share your thoughts in the comments below!&lt;/p&gt;

</description>
      <category>azure</category>
      <category>adf</category>
      <category>sql</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Node.js Deprecation Issues: Debugging Syntax Errors and Staying Up to Date</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Tue, 18 Feb 2025 12:37:02 +0000</pubDate>
      <link>https://dev.to/sanket00123/nodejs-deprecation-issues-debugging-syntax-errors-and-staying-up-to-date-fj0</link>
      <guid>https://dev.to/sanket00123/nodejs-deprecation-issues-debugging-syntax-errors-and-staying-up-to-date-fj0</guid>
      <description>&lt;p&gt;Node.js updates bring exciting new features, but they also introduce breaking changes and deprecated functionalities. One moment, your code is running smoothly, and the next—boom! You’re hit with a cryptic error message.  &lt;/p&gt;

&lt;p&gt;Recently, I encountered this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Unexpected identifier 'assert' at compileSourceTextModule...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, I thought it was a simple syntax mistake. But after some troubleshooting, I realized the issue wasn’t my code—it was my &lt;strong&gt;Node.js version&lt;/strong&gt;. A colleague’s app worked fine, but mine didn’t. The difference? &lt;strong&gt;I was running Node.js 22.7.0, while they were on 20.10.0.&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;The quickest fix? &lt;strong&gt;Downgrade Node.js to match their version.&lt;/strong&gt; And just like that, the issue was resolved.  &lt;/p&gt;

&lt;p&gt;This raised an important question:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you identify if an issue is due to a Node.js deprecation?
&lt;/li&gt;
&lt;li&gt;What are the most common syntax errors caused by version mismatches?
&lt;/li&gt;
&lt;li&gt;How can you proactively track changes and avoid these surprises?
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s break it down. 🚀  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 When Node.js Deprecations Cause Errors
&lt;/h2&gt;

&lt;p&gt;Node.js deprecations usually follow a pattern:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Soft Deprecation&lt;/strong&gt; – The feature works but logs warnings in newer versions.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hard Deprecation&lt;/strong&gt; – The feature is removed, leading to syntax or runtime errors.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Breaking Changes&lt;/strong&gt; – APIs are modified or replaced, requiring code updates.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you suddenly face a &lt;strong&gt;syntax error that wasn’t there before&lt;/strong&gt;, chances are your Node.js version changed, and a previously supported feature no longer works.  &lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ Common Node.js Version-Related Errors
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🛑 &lt;strong&gt;1. Unexpected Identifier 'assert'&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This is exactly what I faced. The &lt;code&gt;assert&lt;/code&gt; module changed in newer Node.js versions, and my code no longer worked.  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;How to Fix:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check your Node.js version:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If your peers’ code is working, match their version using &lt;code&gt;nvm&lt;/code&gt; (Node Version Manager):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  nvm &lt;span class="nb"&gt;install &lt;/span&gt;20.10.0
  nvm use 20.10.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Alternatively, update your code to use &lt;code&gt;assert/strict&lt;/code&gt; if you're using a newer Node.js version.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛑 &lt;strong&gt;2. Module System Errors&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ever seen this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SyntaxError: Cannot use import statement outside a module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;How to Fix:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If using ES Modules, ensure &lt;code&gt;package.json&lt;/code&gt; has:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"module"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If using CommonJS, replace &lt;code&gt;import&lt;/code&gt; with &lt;code&gt;require()&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Stick to &lt;strong&gt;one module system&lt;/strong&gt; throughout your project.
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🛑 &lt;strong&gt;3. Callback Deprecations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Older Node.js versions relied on callback-based async functions, but newer versions favor &lt;code&gt;async/await&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;strong&gt;How to Fix:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the modern &lt;code&gt;fs.promises.readFile()&lt;/code&gt; method:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;promises&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;file.txt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes your code cleaner and aligns with the latest Node.js standards.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🛠️ How to Identify If an Issue Is Due to Node.js Version Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  📌 &lt;strong&gt;1. Compare Your Node.js Version&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, check what version you’re running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your code was working before but now it’s broken, compare your version with a peer whose setup is working.  &lt;/p&gt;

&lt;h3&gt;
  
  
  📌 &lt;strong&gt;2. Check for Deprecation Warnings&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run your app with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node &lt;span class="nt"&gt;--trace-deprecation&lt;/span&gt; index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will print detailed warnings if a deprecated feature is being used.  &lt;/p&gt;

&lt;h3&gt;
  
  
  📌 &lt;strong&gt;3. Read Node.js Changelogs&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Visit the official &lt;a href="https://nodejs.org/en/blog/release/" rel="noopener noreferrer"&gt;Node.js Release Notes&lt;/a&gt; to see if recent changes impact your code.  &lt;/p&gt;




&lt;h2&gt;
  
  
  📡 How to Stay Up to Date with Node.js Changes
&lt;/h2&gt;

&lt;p&gt;Instead of waiting for errors to pop up, &lt;strong&gt;proactively monitor Node.js updates&lt;/strong&gt;:  &lt;/p&gt;

&lt;h3&gt;
  
  
  🔄 &lt;strong&gt;1. Use Node Version Manager (NVM)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of manually upgrading or downgrading Node.js, use &lt;code&gt;nvm&lt;/code&gt; to quickly switch between versions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nvm &lt;span class="nb"&gt;install &lt;/span&gt;20
nvm use 20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps you test your app across multiple Node.js versions without reinstalling.  &lt;/p&gt;

&lt;h3&gt;
  
  
  📰 &lt;strong&gt;2. Subscribe to Node.js Updates&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Follow &lt;a href="https://nodejs.org/en/blog/" rel="noopener noreferrer"&gt;Node.js Blog&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Keep an eye on &lt;a href="https://github.com/nodejs/node/discussions" rel="noopener noreferrer"&gt;GitHub Discussions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Join developer forums like &lt;a href="https://www.reddit.com/r/node/" rel="noopener noreferrer"&gt;r/node&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ⚡ &lt;strong&gt;3. Automate Dependency Checks&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;Dependabot&lt;/strong&gt; or &lt;strong&gt;Renovate&lt;/strong&gt; to get alerts when dependencies introduce breaking changes.  &lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Best Practices to Avoid Node.js Deprecation Issues
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Use LTS (Long-Term Support) Versions&lt;/strong&gt; – Avoid unstable releases for production.  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Test Your Code on Multiple Node.js Versions&lt;/strong&gt; – If you maintain a project, ensure compatibility across different Node.js versions.  &lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Read Deprecation Warnings&lt;/strong&gt; – If a feature is marked as deprecated, update your code &lt;strong&gt;before&lt;/strong&gt; it breaks.  &lt;/p&gt;




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

&lt;p&gt;In my case, downgrading Node.js &lt;strong&gt;immediately resolved the issue&lt;/strong&gt;—a quick and practical fix. But long term, the best approach is to stay informed, track deprecations, and update code before it becomes a problem.  &lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Key takeaway?&lt;/strong&gt; When faced with syntax errors after a Node.js update, check your version first. If something worked before but doesn’t now, a version mismatch might be the culprit.  &lt;/p&gt;

&lt;p&gt;Whether you downgrade Node.js like I did or update your code to match the latest standards, staying ahead of deprecations will save you time and frustration. 🚀  &lt;/p&gt;




&lt;h2&gt;
  
  
  📖 Further Reading &amp;amp; Resources
&lt;/h2&gt;

&lt;p&gt;🔗 &lt;a href="https://nodejs.org/en/blog/release/" rel="noopener noreferrer"&gt;Node.js Release Notes&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://nodejs.org/en/docs/" rel="noopener noreferrer"&gt;Node.js API Docs&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://github.com/nvm-sh/nvm" rel="noopener noreferrer"&gt;NVM - Node Version Manager&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://www.whitesourcesoftware.com/free-developer-tools/renovate" rel="noopener noreferrer"&gt;Renovate - Automate Dependency Updates&lt;/a&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔗 Related Read
&lt;/h2&gt;

&lt;p&gt;If you enjoyed this breakdown, you might also like my previous blog where I tackled &lt;strong&gt;building a robust data ingestion pipeline&lt;/strong&gt; using Azure Data Factory. It’s a deep dive into handling real-world challenges like pagination, schema validation, and performance tuning.  &lt;/p&gt;

&lt;p&gt;📖 &lt;strong&gt;&lt;a href="https://dev.to/sanket00123/behind-the-scenes-building-a-dynamic-data-ingestion-pipeline-with-azure-data-factory-2ia7"&gt;Read it here&lt;/a&gt;&lt;/strong&gt;  &lt;/p&gt;




</description>
      <category>node</category>
      <category>javascript</category>
      <category>debugging</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Beyond Data Ingestion: Advanced Strategies for Optimizing API Data Pipelines</title>
      <dc:creator>SANKET PATIL</dc:creator>
      <pubDate>Fri, 29 Nov 2024 07:08:59 +0000</pubDate>
      <link>https://dev.to/sanket00123/beyond-data-ingestion-advanced-strategies-for-optimizing-api-data-pipelines-3613</link>
      <guid>https://dev.to/sanket00123/beyond-data-ingestion-advanced-strategies-for-optimizing-api-data-pipelines-3613</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/sanket00123/behind-the-scenes-building-a-dynamic-data-ingestion-pipeline-with-azure-data-factory-2ia7"&gt;previous blog&lt;/a&gt;, we explored how to build a dynamic and robust data ingestion pipeline using Azure Data Factory. The feedback from the community was overwhelming, and it sparked some amazing discussions! Thanks to the curiosity and questions from my peers, I’m excited to share this second installment, diving deeper into the advanced challenges and solutions for optimizing API-driven data pipelines.&lt;/p&gt;

&lt;p&gt;If you haven’t read the first post, no worries — this one stands alone! However, if you're curious about schema alignment, dealing with duplicate data, and the foundational aspects of building a smarter data pipeline, feel free to check it out &lt;a href="https://dev.to/sanket00123/behind-the-scenes-building-a-dynamic-data-ingestion-pipeline-with-azure-data-factory-2ia7"&gt;here&lt;/a&gt;.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 &lt;strong&gt;Key Lessons From Real-World Scenarios&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After publishing the first post, I received insightful questions on topics ranging from schema alignment to managing API timeouts for massive datasets. In this blog, I’ll share the answers and some bonus learnings we uncovered along the way. &lt;/p&gt;




&lt;h3&gt;
  
  
  🛠️ &lt;strong&gt;1. Schema Alignment Simplified&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;One major hurdle in data pipelines is ensuring schema alignment across systems. Here’s how we tackled it:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fetching the Schema&lt;/strong&gt;: The API we used provided a dedicated endpoint to retrieve schema details. By validating this schema in &lt;strong&gt;SQL Server Management Studio (SSMS)&lt;/strong&gt;, we ensured that the table structures, data types, and constraints matched the database requirements.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Handling Timeouts&lt;/strong&gt;: Schema updates for large datasets often resulted in timeouts. To address this, we temporarily scaled up database resources, which significantly reduced the time required to save schema changes. Once the updates were complete, resources were scaled back to their original configuration to avoid unnecessary costs.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧹 &lt;strong&gt;2. Automating Duplicate Handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Data duplication is a common issue, especially when ingesting large datasets. While manual identification and deletion are possible, automation is key for efficiency. Here’s the SQL query we used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;DuplicateRecords&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;ROW_NUMBER&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;OVER&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;PARTITION&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;recordId&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;recordId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;row_num&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;my_table&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;my_table&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;recordId&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;recordId&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;DuplicateRecords&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;row_num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  💡 Pro Tip:
&lt;/h4&gt;

&lt;p&gt;While this query works for one-time cleanup, you can integrate it into a stored procedure or pipeline step for ongoing automation. This ensures data remains clean without manual intervention.  &lt;/p&gt;




&lt;h3&gt;
  
  
  ⚙️ &lt;strong&gt;3. Optimizing Throughput Without Over-Scaling Hardware&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Ingesting large datasets efficiently can be tricky, especially when hardware scaling only yields marginal improvements. In our case, the initial approach involved upscaling resources, but the gains were not significant. We reverted to the original plan and focused on the following strategies:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Batch Processing&lt;/strong&gt;: Restructure the pipeline to handle larger chunks of data in fewer API calls, thereby reducing network overhead.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Parallelization&lt;/strong&gt;: Execute multiple data ingestion operations in parallel to utilize existing hardware more effectively.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Switching Tools&lt;/strong&gt;: Replace the web activity with more efficient tools, such as &lt;strong&gt;Azure Function Apps&lt;/strong&gt; or &lt;strong&gt;Logic Apps&lt;/strong&gt;, which can handle larger payloads per request.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Data Compression&lt;/strong&gt;: If the API supports compression (e.g., GZIP), use it to reduce payload size and processing time.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By combining these techniques, we improved throughput without scaling hardware, achieving a cost-effective and efficient solution.  &lt;/p&gt;




&lt;h3&gt;
  
  
  ⏳ &lt;strong&gt;4. Tackling API Timeouts for Long-Running Data Retrieval&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Timeouts are a common challenge when working with APIs, especially during large-scale data ingestion. To address this:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API Documentation Review&lt;/strong&gt;: We thoroughly reviewed the API's documentation to understand its timeout settings and limitations. However, it did not provide explicit solutions for handling prolonged data retrieval.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Handling Specific Timeout Scenarios&lt;/strong&gt;: During one operation involving a particularly large dataset, a timeout occurred after processing a significant portion of the records. To manage this, we implemented the following strategies:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Pagination&lt;/strong&gt;: Breaking the data retrieval into smaller, paginated chunks to keep requests within the timeout limits.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental Fetching&lt;/strong&gt;: Adjusting request sizes dynamically based on observed timeout patterns to avoid failures.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retry Mechanism&lt;/strong&gt;: Adding retry logic in the pipeline for automatic recovery from temporary failures.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;These adjustments helped stabilize the pipeline, allowing for reliable ingestion even in the face of API limitations.  &lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 &lt;strong&gt;Key Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Building and optimizing data pipelines is a continuous learning process. The strategies shared here were shaped by real-world challenges, experimentation, and collaboration with my peers.  &lt;/p&gt;

&lt;p&gt;Have you faced similar challenges? Got better ideas or insights? I’d love to hear your thoughts and experiences in the comments below!  &lt;/p&gt;




&lt;h2&gt;
  
  
  📢 &lt;strong&gt;Let’s Continue the Conversation&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you haven’t read &lt;a href="https://dev.to/sanket00123/behind-the-scenes-building-a-dynamic-data-ingestion-pipeline-with-azure-data-factory-2ia7"&gt;my first blog&lt;/a&gt; yet, check it out for insights into building a dynamic data pipeline. And if you enjoyed this post, don’t forget to &lt;strong&gt;like&lt;/strong&gt;, &lt;strong&gt;share&lt;/strong&gt;, and leave your feedback!  &lt;/p&gt;

&lt;p&gt;🚀 &lt;strong&gt;Together, let’s master the art of building smarter pipelines!&lt;/strong&gt;  &lt;/p&gt;

</description>
      <category>dataengineering</category>
      <category>azuredatafactory</category>
      <category>apipagination</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
