<?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: Mohsindev369</title>
    <description>The latest articles on DEV Community by Mohsindev369 (@mohsindev369).</description>
    <link>https://dev.to/mohsindev369</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%2F1056998%2F82886af3-622d-465d-a5ff-5d2865f8fbc3.jpeg</url>
      <title>DEV Community: Mohsindev369</title>
      <link>https://dev.to/mohsindev369</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mohsindev369"/>
    <language>en</language>
    <item>
      <title>A webhook retry can pay a customer twice, and two checks that stop it</title>
      <dc:creator>Mohsindev369</dc:creator>
      <pubDate>Fri, 30 Oct 2026 00:38:30 +0000</pubDate>
      <link>https://dev.to/mohsindev369/a-webhook-retry-can-pay-a-customer-twice-and-two-checks-that-stop-it-2cem</link>
      <guid>https://dev.to/mohsindev369/a-webhook-retry-can-pay-a-customer-twice-and-two-checks-that-stop-it-2cem</guid>
      <description>&lt;p&gt;If you sell credits or usage through Stripe, LemonSqueezy or Polar, your webhook handler will receive the same event more than once. Providers retry when your server is slow, when a deploy lands mid-request, when a response gets lost. If the handler does &lt;code&gt;balance += 100&lt;/code&gt; every time it sees &lt;code&gt;checkout.session.completed&lt;/code&gt;, somebody eventually gets paid twice.&lt;/p&gt;

&lt;p&gt;The fix is two checks, not one. Here is what each one does and why the second exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 1: de-dupe on the event id, inside the same transaction
&lt;/h2&gt;

&lt;p&gt;Keep a table of events you have handled, keyed by provider and event id. Insert before you do any work, and skip the work if the insert did nothing:&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;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inserted&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;tx&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;billingWebhookEvents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;eventType&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onConflictDoNothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returning&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;eventId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;billingWebhookEvents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eventId&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;inserted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// a retry of an event we already handled&lt;/span&gt;

  &lt;span class="c1"&gt;// ...do the actual work with tx&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The primary key is &lt;code&gt;(provider, event_id)&lt;/code&gt;. The detail that matters is the transaction. If the work throws, the de-dupe row rolls back with it, so the provider's next retry is processed instead of being swallowed as already handled. The common version of this bug checks first and processes after, and a delivery that failed halfway is then lost for good.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check 2: a unique constraint on the thing being paid for
&lt;/h2&gt;

&lt;p&gt;Event ids are the provider's idea of uniqueness, not yours. One checkout can in principle reach you under two different event ids, and once several billing providers sit behind one interface you can't rule it out. So the purchase itself gets a unique key, and you insert it before the balance moves:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;purchase&lt;/span&gt;&lt;span class="p"&gt;]&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;tx&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;creditPurchases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;teamId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;providerCheckoutId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;credits&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onConflictDoNothing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;returning&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;creditPurchases&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;purchase&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="c1"&gt;// this checkout already paid out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the row already exists, the credits were granted for this checkout, whatever event id carried it. Check 1 protects you from redelivery. Check 2 protects you from your own assumptions about the provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the increment atomic
&lt;/h2&gt;

&lt;p&gt;The last piece is easy to miss. Do the increment in SQL, not in JavaScript:&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;await&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;credits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;teamId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;packCredits&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onConflictDoUpdate&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;credits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teamId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;credits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&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;packCredits&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;balance + N&lt;/code&gt; runs inside the database, so two concurrent deliveries for the same team can't read the same starting balance and overwrite each other. A read, add, write sequence in application code can.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test it against a real Postgres
&lt;/h2&gt;

&lt;p&gt;This is the part that earned its keep. Mocks agree with whatever you wrote, because a mock doesn't enforce a unique constraint or roll back a transaction. A real Postgres does both. The tests that matter deliver the same event twice and the same checkout under two different event ids, then assert the balance moved once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no-ops a redelivery of the exact same event id&lt;/li&gt;
&lt;li&gt;doesn't double-grant when the same checkout is delivered under two different event ids&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When I added tests like these against a real database, they caught two real bugs in my own billing code that I had read past more than once.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to copy
&lt;/h2&gt;

&lt;p&gt;If you only take one thing from this: put the de-dupe row and the work in one transaction, and give the paid thing its own unique key. Everything else follows from those two.&lt;/p&gt;

&lt;p&gt;This is the pattern in &lt;a href="https://keelkit.dev" rel="noopener noreferrer"&gt;Keel&lt;/a&gt;, the Next.js SaaS starter I'm building and selling. The webhook handler, the credit grant and the tests are all in the repo, and there is a &lt;a href="https://keelkit.dev/demo" rel="noopener noreferrer"&gt;demo with no sign-up&lt;/a&gt; if you want to see the product around it.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>postgres</category>
      <category>saas</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Tip for freelancers and Clients going to hire freelancers</title>
      <dc:creator>Mohsindev369</dc:creator>
      <pubDate>Wed, 17 Jan 2024 19:52:37 +0000</pubDate>
      <link>https://dev.to/mohsindev369/tip-for-freelancers-and-clients-going-to-hire-freelancers-20hi</link>
      <guid>https://dev.to/mohsindev369/tip-for-freelancers-and-clients-going-to-hire-freelancers-20hi</guid>
      <description>&lt;p&gt;Having a good order brief makes ALL the difference!&lt;/p&gt;

&lt;p&gt;For all web design clients looking for freelancers, please do yourself (and your chosen freelancer) a favor by creating a clear and concise order brief.&lt;/p&gt;

&lt;p&gt;It helps us understand your vision, budget, timeline, and specific needs. This leads to:&lt;/p&gt;

&lt;p&gt;✅ Better communication: Less back-and-forth, more focused collaboration.&lt;br&gt;
✅ Fewer revisions: Reduced risk of missed expectations and rework.&lt;br&gt;
✅ Smoother project flow: Everything runs smoothly from start to finish.&lt;/p&gt;

&lt;p&gt;If I were your freelancer I would need the following in your order brief&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Project Overview:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ Project Name:&lt;br&gt;
✅ Company Name:&lt;br&gt;
✅ Website URL (if applicable):&lt;br&gt;
✅ Project Description: Briefly summarize your project goals and desired outcomes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Target Audience:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ Who are you trying to reach with your website?&lt;br&gt;
✅ What are their needs and expectations?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Functionality Requirements:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ What features and functionality do you need on your website?&lt;br&gt;
✅ Are there any specific integrations or plugins you require?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design Preferences:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ Do you have any specific design styles or references in mind?&lt;/p&gt;

&lt;p&gt;// Side Note: let the designer make colors, fonts, and overall aesthetic decisions don't micro-manage if he's the expert Let him cook.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Budget and Timeline:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;✅ What is your estimated budget for this project?&lt;br&gt;
✅ What is your desired timeline for completion?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Content:
✅ Do you have any existing content that can be used?
✅ What additional content needs to be created?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Bonus:&lt;br&gt;
Include any relevant examples of websites you like for inspiration.&lt;br&gt;
Remember: The more detailed your order brief, the better equipped your freelancer will be to deliver a website that exceeds your expectations.&lt;br&gt;
Let's make web design projects a success for everyone!&lt;/p&gt;

&lt;p&gt;hashtag#webdesign hashtag#freelancer hashtag#orderbrief hashtag#projectmanagement hashtag#tips&lt;/p&gt;

</description>
    </item>
    <item>
      <title>🎯 Overcoming Impostor Syndrome in the World of Web Development 💻</title>
      <dc:creator>Mohsindev369</dc:creator>
      <pubDate>Fri, 25 Aug 2023 19:10:39 +0000</pubDate>
      <link>https://dev.to/mohsindev369/overcoming-impostor-syndrome-in-the-world-of-web-development-45pp</link>
      <guid>https://dev.to/mohsindev369/overcoming-impostor-syndrome-in-the-world-of-web-development-45pp</guid>
      <description>&lt;p&gt;Hey There 👋&lt;/p&gt;

&lt;p&gt;Today, I wanted to talk about something that many of us in the web development community have likely experienced at some point in our careers: Impostor Syndrome. 🤔&lt;/p&gt;

&lt;p&gt;Impostor Syndrome is that nagging feeling of self-doubt and inadequacy, even in the face of accomplishments and evidence of competence. It's that voice in our heads that whispers, "Do I really belong here?" or "Am I just lucky, or do I actually know what I'm doing?" Trust me, you're not alone if you've ever had these thoughts. 🙋‍♂️🙋‍♀️&lt;/p&gt;

&lt;p&gt;In the fast-paced and ever-evolving world of web development, it's easy to feel like you're falling behind or that you're not as skilled as your peers. But here's the truth: You've come a long way, and you deserve to be where you are! 🚀&lt;/p&gt;

&lt;p&gt;Here are a few strategies I've found helpful in combating Impostor &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Acknowledge Your Achievements:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Take a moment to reflect on your journey. Remember the projects you've successfully delivered, the complex code you've tackled, and the problems you've solved. These accomplishments are proof of your skills and dedication.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Embrace Continuous Learning:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Web development is all about growth. Instead of fixating on what you don't know, focus on what you're learning. Every challenge you overcome adds to your expertise.&lt;/p&gt;

&lt;p&gt;Talk About It: Don't be afraid to open up to your colleagues or mentors about how you're feeling. You'll likely find that they've experienced similar thoughts and can provide valuable perspective.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Celebrate Progress:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Break down your larger goals into smaller milestones. Celebrate each achievement along the way. It's a great way to remind yourself of your capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Remember You're Not Alone:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Impostor Syndrome is more common than you think. Many successful developers have dealt with it too. It's a sign that you care about your work and want to do your best.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Practice Self-Compassion:&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Treat yourself with kindness. Remember that making mistakes is a natural part of learning and growing. Don't be too hard on yourself.&lt;/p&gt;

&lt;p&gt;Let's turn Impostor Syndrome into Impostor Strength! 🦸‍♂️🦸‍♀️ Remember, every challenge you face and overcome is a step forward in your journey. You belong in this field, and your unique skills contribute to the vibrant web development community.&lt;/p&gt;

&lt;p&gt;Have you experienced Impostor Syndrome? How do you overcome it? Let's start a conversation and support each other in the comments below! 👇&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>impostorsyndrome</category>
      <category>techcommunity</category>
      <category>personalgrowth</category>
    </item>
    <item>
      <title>Get network information using JavaScript and optimize your app</title>
      <dc:creator>Mohsindev369</dc:creator>
      <pubDate>Fri, 21 Apr 2023 22:33:32 +0000</pubDate>
      <link>https://dev.to/mohsindev369/get-network-information-using-javascript-fn4</link>
      <guid>https://dev.to/mohsindev369/get-network-information-using-javascript-fn4</guid>
      <description>&lt;p&gt;Have you every wanted to optimize your web application behavior based on the user internet performance? Maybe loading content in different qualities?&lt;/p&gt;

&lt;h2&gt;
  
  
  Network Information API
&lt;/h2&gt;

&lt;p&gt;This API is accessed through the &lt;code&gt;navigator.connection&lt;/code&gt; property. Here are some of the properties.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;effectiveType&lt;/li&gt;
&lt;li&gt;downlink&lt;/li&gt;
&lt;li&gt;errt&lt;/li&gt;
&lt;li&gt;saveData&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;effectiveType&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;effectiveType&lt;/code&gt; property returns the effective type of the current connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;navigator.connection.effectiveType //'slow-2g','2g','3g','4g'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;downlink&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;downlink&lt;/code&gt; property returns the effective bandwidth.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;navigator.connection.downlink //Bandwidth in mbps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rrt&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;rrt&lt;/code&gt; property returns the round-trip time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;navigator.connection.rrt //round-trip time (ms)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;saveData&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;saveData&lt;/code&gt; property returns a Boolean, Weather the user's data-saver is on or off.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;navigator.connection.saveData //true or false 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Using it in a practice example
&lt;/h2&gt;

&lt;p&gt;Less say we want to represent a high quality video, We first make sure that data-saver is not enabled. And if the internet speed meets their requirements, We load the video accordingly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(
!navigator.connection.saveData &amp;amp;&amp;amp;
navigator.connection.effectiveType === '4g' &amp;amp;&amp;amp;
navigator.connection.downlink&amp;gt;2
) 
{
 loadVideo("4k")
} else {
loadVideo("low-quality")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading. This I my first blog so sorry if there is any errors. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>network</category>
      <category>optimazion</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
