<?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: Fahim Ahammed Firoz</title>
    <description>The latest articles on DEV Community by Fahim Ahammed Firoz (@fahimahammed).</description>
    <link>https://dev.to/fahimahammed</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1196293%2Fa1f8d64f-0d98-495c-ab08-c9127998fe69.jpeg</url>
      <title>DEV Community: Fahim Ahammed Firoz</title>
      <link>https://dev.to/fahimahammed</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fahimahammed"/>
    <language>en</language>
    <item>
      <title>Understanding Docker Networks (Easy Concept Explanation)</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Sun, 16 Nov 2025 14:27:45 +0000</pubDate>
      <link>https://dev.to/fahimahammed/understanding-docker-networks-easy-concept-explanation-4j9h</link>
      <guid>https://dev.to/fahimahammed/understanding-docker-networks-easy-concept-explanation-4j9h</guid>
      <description>&lt;p&gt;A Docker Network is basically a virtual space where containers can communicate with each other. By default, every Docker container is isolated, meaning it cannot see or talk to any other container. This isolation is good for security, but in real projects we usually run multiple containers together, like a backend API, a frontend, and a database. If these containers cannot talk to each other, nothing will work. That is why Docker Networks exist, they allow containers to communicate safely and easily.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mpseu2icvtzkzo5az6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F99mpseu2icvtzkzo5az6.png" alt=" " width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can think of a Docker Network as a room, and containers as people inside that room. People in the same room can talk to each other freely. People in different rooms cannot communicate unless you create a connection between the rooms. In the same way, containers inside the same Docker Network can communicate smoothly, while containers in different networks remain isolated.&lt;/p&gt;

&lt;p&gt;Docker has different types of networks, but the most commonly used one is the Bridge Network. This network works like a private area where related containers, such as your API and database, stay together and can interact. The Host Network removes the boundary between the container and the machine running it, which makes communication faster but less isolated. The None Network isolates the container completely, giving it no network access at all. The Overlay Network is used in large or multi server environments where containers on different machines need to communicate as if they were in the same room.&lt;/p&gt;

&lt;p&gt;One of the best things about Docker Networks is that containers can talk to each other using their names instead of IP addresses. For example, your API can reach the database simply by using its container name. Docker automatically manages all the underlying network rules, which makes development much easier.&lt;/p&gt;

&lt;p&gt;In simple words, a Docker Network is like Wi Fi for containers. If containers are connected to the same network, they can communicate. If they are not, they stay isolated.&lt;/p&gt;

&lt;p&gt;Docker networking keeps your applications structured, secure, and scalable, and understanding this concept is a big step toward mastering container based development.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>dockernetwork</category>
      <category>development</category>
    </item>
    <item>
      <title>কেন Stripe Date-Based API Versioning ব্যবহার করে? (কেন Traditional Versioning করে না)</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Wed, 08 Oct 2025 13:35:16 +0000</pubDate>
      <link>https://dev.to/fahimahammed/ken-stripe-date-based-api-versioning-bybhaar-kre-ken-traditional-versioning-kre-naa-1j9</link>
      <guid>https://dev.to/fahimahammed/ken-stripe-date-based-api-versioning-bybhaar-kre-ken-traditional-versioning-kre-naa-1j9</guid>
      <description>&lt;p&gt;প্রায় সবাই জানি Stripe-এর API অসাধারণ। কিন্তু  জানেন কি কেন তারা traditional /v1, /v2 versioning ব্যবহার না করে, বরং date-based versioning ব্যবহার করে?&lt;/p&gt;

&lt;p&gt;এটা মূলত Stripe-এর developer-friendly এবং stable API design-এর ঝলক।&lt;/p&gt;

&lt;p&gt;Traditional Versioning-এর কিছু সীমাবদ্ধতা রয়েছে। উদাহরণস্বরূপ, যখন একটি API /v1/customers থেকে /v2/customers-এ আপডেট হয়, তখন সাধারণত endpoint structure, data format, এবং response shape-এর বড় পরিবর্তন আসে। এর ফলে existing integrations হঠাৎ ভেঙে যেতে পারে এবং developers-কে নতুন version-এ migrate করতে অনেক সময় ও effort দিতে হয়। এছাড়া, একাধিক version maintain করাও জটিল হয়ে যায়। অর্থাৎ, Traditional Versioning বড় পরিবর্তনের ক্ষেত্রে risk তৈরি করে এবং integration-কে কম stable রাখে।&lt;/p&gt;

&lt;p&gt;Stripe-এর Date-Based Versioning হল এমন একটি পদ্ধতি যেখানে প্রতিটি API version একটি নির্দিষ্ট তারিখের সঙ্গে mark করা থাকে, যেমন 2025-09-30.clover.  এতে করে প্রতিটি major বা monthly release সহজে track করা যায়।&lt;/p&gt;

&lt;p&gt;Major release-এ বড় পরিবর্তন (যা backward-compatible নয়) আনা হয়, কিন্তু monthly release-এ শুধু backward-compatible ছোট পরিবর্তন আসে। এই পদ্ধতিতে, আপনার integration যেই version-এ pinned থাকে, তা নতুন update এলেও ভাঙবে না। Developer রা চাইলে পরবর্তীতে step-by-step নতুন version-এ safely migrate করতে পারেন।&lt;/p&gt;

&lt;p&gt;Stripe internally প্রতিটি request handle করে compatibility layer দিয়ে।&lt;/p&gt;

&lt;p&gt;Main codebase সর্বদা latest থাকে, কিন্তু পুরোনো version-এর জন্য response backward-compatible হয়।&lt;/p&gt;

&lt;p&gt;Stripe-এর SDK যেমন stripe-node, stripe-python, release time-এর API version-এর সাথে pinned থাকে। ফলে Type mismatch বা API inconsistency-এর ঝুঁকি কমে যায়।&lt;/p&gt;

&lt;p&gt;Webhook endpoint তৈরির সময় যেই version নির্বাচন করা হয়, সেই version-এর data format সবসময় ঠিক থাকে। নতুন update আসলেও আপনার webhook break হয় না।&lt;/p&gt;

&lt;p&gt;সহজভাবে- &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traditional versioning = একবারে big change, risk বেশি&lt;/li&gt;
&lt;li&gt;Date-based versioning = step by step small change, integration always stable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stripe-এ এটি win-win. &lt;/p&gt;

&lt;p&gt;Stripe-এর date-based versioning দেখায় কিভাবে innovation এবং stability একসাথে রাখা যায়। Integration সহজ, upgrades smooth, এবং system সবসময় reliable.&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Building an AI Chat Rate Limiter with Node.js, Express, and Vercel AI SDK</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Sat, 20 Sep 2025 16:04:14 +0000</pubDate>
      <link>https://dev.to/fahimahammed/building-an-ai-chat-rate-limiter-with-nodejs-express-and-vercel-ai-sdk-5240</link>
      <guid>https://dev.to/fahimahammed/building-an-ai-chat-rate-limiter-with-nodejs-express-and-vercel-ai-sdk-5240</guid>
      <description>&lt;p&gt;When building AI chat applications, one of the main challenges is &lt;strong&gt;controlling costs&lt;/strong&gt;. Each AI request has a cost, so you cannot allow unlimited usage. A &lt;strong&gt;rate limiter&lt;/strong&gt; helps solve this by restricting how many requests each user can make in a fixed time period.&lt;/p&gt;

&lt;p&gt;In this article, we will look at how to build a &lt;strong&gt;chatbot backend&lt;/strong&gt; using Node.js, Express, and the Vercel AI SDK. Our system uses a &lt;strong&gt;fixed window rate limiting algorithm&lt;/strong&gt; to manage usage for different user types: Guest, Free, and Premium.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Rate Limiting?
&lt;/h2&gt;

&lt;p&gt;Rate limiting ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fair usage for all users&lt;/li&gt;
&lt;li&gt;Protection from abuse&lt;/li&gt;
&lt;li&gt;Cost control for AI services&lt;/li&gt;
&lt;li&gt;Predictable system performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if a Guest makes 1,000 requests per hour, your costs can skyrocket. With a limiter, you decide how many requests are allowed.&lt;/p&gt;




&lt;h2&gt;
  
  
  User Types and Limits
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Type&lt;/th&gt;
&lt;th&gt;Limit (per hour)&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Guest&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;No login required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Logged-in users with free plan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Premium&lt;/td&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;Logged-in users with premium plan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The system identifies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Guests&lt;/strong&gt; by IP address&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logged-in users&lt;/strong&gt; by their &lt;code&gt;user.id&lt;/code&gt; (from JWT token)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How the Rate Limiter Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;A request is sent to &lt;code&gt;/api/chat&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If there is a JWT token, it is verified. If missing, the user is a &lt;strong&gt;Guest&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The system decides the limit based on user type:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Guest = 3&lt;/li&gt;
&lt;li&gt;Free = 10&lt;/li&gt;
&lt;li&gt;Premium = 50&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The request counter is checked for the current &lt;strong&gt;1-hour window&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the user has requests left, the system forwards the query to the AI SDK.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the limit is exceeded, the server returns a &lt;strong&gt;429 error&lt;/strong&gt; with a clear message.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Fixed Window Algorithm
&lt;/h2&gt;

&lt;p&gt;We use a &lt;strong&gt;Fixed Window Algorithm&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep a count of requests per user (or IP).&lt;/li&gt;
&lt;li&gt;If the request is within the same window (1 hour), increase the count.&lt;/li&gt;
&lt;li&gt;If the window has expired, reset the count and start a new window.&lt;/li&gt;
&lt;li&gt;If the count is above the limit, reject the request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example in memory store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user123"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"windowStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1695206400000&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means user123 has made 7 requests since the last window started.&lt;/p&gt;




&lt;h2&gt;
  
  
  Flow Diagram
&lt;/h2&gt;

&lt;p&gt;The process can be explained with this flow:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkttmol7bu2vj8toi4zxa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkttmol7bu2vj8toi4zxa.png" alt="SD" width="800" height="927"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check if the request has a JWT token.&lt;/li&gt;
&lt;li&gt;If valid, assign user type (Free or Premium). Otherwise, assign Guest.&lt;/li&gt;
&lt;li&gt;Apply the rate limit based on user type.&lt;/li&gt;
&lt;li&gt;If the user is new, start tracking requests.&lt;/li&gt;
&lt;li&gt;If the time window has expired, reset the counter.&lt;/li&gt;
&lt;li&gt;If the count is within the limit, allow the request. Otherwise, block it.&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;By combining &lt;strong&gt;Express&lt;/strong&gt;, &lt;strong&gt;JWT authentication&lt;/strong&gt;, and the &lt;strong&gt;Vercel AI SDK&lt;/strong&gt;, we built a chatbot backend with &lt;strong&gt;different rate limits for Guests, Free users, and Premium users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This ensures cost control, fair usage, and a better experience for all users.&lt;/p&gt;

&lt;p&gt;Source code: &lt;a href="https://github.com/fahimahammed/chatbot-throttle" rel="noopener noreferrer"&gt;GitHub - chatbot-throttle&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⭐ If you find this project useful, don’t forget to star the repository on GitHub!&lt;/p&gt;

</description>
      <category>ratelimit</category>
      <category>fixedwindow</category>
      <category>aisdk</category>
      <category>aichatratelimiter</category>
    </item>
    <item>
      <title>Protect Your API with Token Bucket Rate Limiting</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Sat, 20 Sep 2025 06:53:32 +0000</pubDate>
      <link>https://dev.to/fahimahammed/protect-your-api-with-token-bucket-rate-limiting-1g9a</link>
      <guid>https://dev.to/fahimahammed/protect-your-api-with-token-bucket-rate-limiting-1g9a</guid>
      <description>&lt;p&gt;When building APIs, chat services, or real-time systems, one of the biggest challenges is preventing clients from overwhelming your server with too many requests. Without protection, a flood of traffic can slow down performance or even crash the system.&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;rate limiting&lt;/strong&gt; comes in. Among the many techniques available, the &lt;strong&gt;Token Bucket Algorithm&lt;/strong&gt; is widely used because it is simple, efficient, and allows for bursts of traffic without losing overall control.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Rate Limiting?
&lt;/h2&gt;

&lt;p&gt;Rate limiting is the process of controlling how many requests a client can send to a server in a given period of time.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A client may be allowed &lt;strong&gt;10 requests per second&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If they exceed that, their additional requests are rejected until the next second begins.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate limiting ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fair resource usage across users&lt;/li&gt;
&lt;li&gt;Protection against abuse, brute-force attacks, or spam&lt;/li&gt;
&lt;li&gt;Improved server stability and reliability&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Token Bucket Algorithm
&lt;/h2&gt;

&lt;p&gt;The Token Bucket Algorithm works like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each client is assigned a &lt;strong&gt;bucket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The bucket has a &lt;strong&gt;capacity&lt;/strong&gt; (for example, 10 tokens).&lt;/li&gt;
&lt;li&gt;Tokens are &lt;strong&gt;refilled at a fixed rate&lt;/strong&gt; (for example, 1 token per second).&lt;/li&gt;
&lt;li&gt;Each request &lt;strong&gt;consumes one token&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If the bucket is empty, the request is &lt;strong&gt;rejected&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach allows &lt;strong&gt;short bursts of requests&lt;/strong&gt; when tokens are available, while still enforcing a long-term average request rate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Token Bucket Flow
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx89fgrcauu00ved6bjdy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx89fgrcauu00ved6bjdy.png" alt="Token Bucket Rate Limiter SD" width="800" height="904"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The steps are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check if the client is new&lt;/strong&gt;&lt;br&gt;
If yes, create a bucket for them with full capacity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Refill tokens&lt;/strong&gt;&lt;br&gt;
Based on the time elapsed since the last refill.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Check if tokens are available&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;If yes, consume one token and accept the request.&lt;/li&gt;
&lt;li&gt;If no, reject the request.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This balance ensures that clients can make quick bursts of requests but cannot exceed the average allowed rate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Implementing Token Bucket in Node.js
&lt;/h2&gt;

&lt;p&gt;Let’s build a simple HTTP server with Token Bucket Rate Limiting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Setup
&lt;/h3&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;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucketCapacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// maximum tokens per user&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refillRate&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="c1"&gt;// tokens per second&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ipBuckets&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;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// store buckets for each IP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We define the bucket size, refill rate, and a map to store each user’s token bucket.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Refill Function
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucket&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;now&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRefillTime&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="c1"&gt;// seconds&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;refillRate&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;refill&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketCapacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;refill&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRefillTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&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;This function calculates how many tokens should be added based on the elapsed time since the last refill, and updates the bucket without exceeding its capacity.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Rate Limiting Middleware
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// If user is new, create a bucket&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;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucketCapacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastRefillTime&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="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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucket&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;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&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="c1"&gt;// consume one token&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request accepted&lt;/span&gt;&lt;span class="se"&gt;\n&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too Many Requests&lt;/span&gt;&lt;span class="se"&gt;\n&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;p&gt;This function manages the bucket for each IP, consumes tokens when available, and rejects requests if tokens are empty.&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Start the Server
&lt;/h3&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;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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;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;Server running at http://localhost:3000/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This starts the server on port 3000, applying the rate limiting logic to every request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Full Code
&lt;/h2&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;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bucketCapacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// maximum tokens per user&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refillRate&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="c1"&gt;// tokens per second&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ipBuckets&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;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// store buckets for each IP&lt;/span&gt;

&lt;span class="c1"&gt;// Refill function&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucket&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;now&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRefillTime&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="c1"&gt;// seconds&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;refill&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elapsed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;refillRate&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;refill&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucketCapacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;refill&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastRefillTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&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="c1"&gt;// Middleware&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;rateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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;ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remoteAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// If user is new, create a bucket&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;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bucketCapacity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;lastRefillTime&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="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;bucket&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ipBuckets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;refillTokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bucket&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;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&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="c1"&gt;// consume one token&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Request accepted&lt;/span&gt;&lt;span class="se"&gt;\n&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;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeHead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&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;Content-Type&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;text/plain&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Too Many Requests&lt;/span&gt;&lt;span class="se"&gt;\n&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;span class="c1"&gt;// Start server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rateLimitMiddleware&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&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;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;Server running at http://localhost:3000/&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;API Gateways&lt;/strong&gt;: prevent abuse by limiting requests per client&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chat Applications&lt;/strong&gt;: stop spamming by controlling message frequency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication Systems&lt;/strong&gt;: slow down brute-force login attempts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IoT Devices&lt;/strong&gt;: manage bursts of data from sensors and devices&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Benefits of Token Bucket
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Allows bursts of requests up to the bucket capacity&lt;/li&gt;
&lt;li&gt;Maintains a steady long-term request rate&lt;/li&gt;
&lt;li&gt;Simple and efficient implementation&lt;/li&gt;
&lt;li&gt;Predictable refill behavior&lt;/li&gt;
&lt;/ul&gt;




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

&lt;p&gt;The Token Bucket Algorithm is a practical and effective way to implement rate limiting. It combines flexibility and control by allowing temporary bursts while maintaining a predictable average request rate.&lt;/p&gt;

&lt;p&gt;If you are building APIs, chat systems, or real-time applications, Token Bucket rate limiting can help you protect your server, ensure fairness, and improve system reliability.&lt;/p&gt;

</description>
      <category>ratelimiting</category>
      <category>tokenbucket</category>
      <category>api</category>
      <category>backend</category>
    </item>
    <item>
      <title>TypedSQL in Prisma: Type-Safe SQL Made Simple</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Fri, 30 Aug 2024 09:35:06 +0000</pubDate>
      <link>https://dev.to/fahimahammed/typedsql-in-prisma-type-safe-sql-made-simple-1n5e</link>
      <guid>https://dev.to/fahimahammed/typedsql-in-prisma-type-safe-sql-made-simple-1n5e</guid>
      <description>&lt;p&gt;TypedSQL is a powerful feature in Prisma that allows developers to write raw SQL queries while maintaining type safety and full integration with Prisma’s TypeScript client. This feature is especially useful for scenarios where complex SQL queries are necessary, but you still want to benefit from Prisma’s type safety, code generation, and developer experience (DX). In this blog, we'll walk through the steps to get started with TypedSQL, how to pass arguments to queries, define argument types, and some best practices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up TypedSQL in Prisma
&lt;/h2&gt;

&lt;p&gt;To start using TypedSQL in your Prisma project, follow these steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install the Required Packages
&lt;/h3&gt;

&lt;p&gt;Ensure that you have &lt;code&gt;@prisma/client&lt;/code&gt; and &lt;code&gt;prisma&lt;/code&gt; installed and updated to at least version 5.19.0. You can do this by running the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @prisma/client@latest
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; prisma@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Enable TypedSQL in Your Schema
&lt;/h3&gt;

&lt;p&gt;Add the &lt;code&gt;typedSql&lt;/code&gt; preview feature flag to your &lt;code&gt;schema.prisma&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generator client {
  provider = "prisma-client-js"
  previewFeatures = ["typedSql"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Create a Directory for SQL Files
&lt;/h3&gt;

&lt;p&gt;Inside your &lt;code&gt;prisma&lt;/code&gt; directory, create a &lt;code&gt;sql&lt;/code&gt; directory where you'll write your SQL queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; prisma/sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Write Your SQL Queries
&lt;/h3&gt;

&lt;p&gt;Create a new &lt;code&gt;.sql&lt;/code&gt; file in the &lt;code&gt;prisma/sql&lt;/code&gt; directory. The file name must be a valid JavaScript identifier and cannot start with a &lt;code&gt;$&lt;/code&gt;. For example, let's create a &lt;code&gt;getUsersWithPosts.sql&lt;/code&gt; file:&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="c1"&gt;-- prisma/sql/getUsersWithPosts.sql&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nv"&gt;"postCount"&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"User"&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"Post"&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;u&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;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"authorId"&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Generate the Prisma Client
&lt;/h3&gt;

&lt;p&gt;To generate TypeScript functions and types for your SQL queries, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prisma generate &lt;span class="nt"&gt;--sql&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want Prisma to regenerate the client automatically after every change, you can use the &lt;code&gt;--watch&lt;/code&gt; flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;prisma generate &lt;span class="nt"&gt;--sql&lt;/span&gt; &lt;span class="nt"&gt;--watch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Use TypedSQL Queries in Your Code
&lt;/h3&gt;

&lt;p&gt;You can now import and use your SQL queries in your TypeScript code:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&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;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUsersWithPosts&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;@prisma/client/sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&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;PrismaClient&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;usersWithPostCounts&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;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$queryRawTyped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getUsersWithPosts&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;usersWithPostCounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing Arguments to TypedSQL Queries
&lt;/h2&gt;

&lt;p&gt;To pass arguments to your TypedSQL queries, you can use parameterized queries. This allows you to write flexible and reusable SQL statements while maintaining type safety.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Passing Parameters
&lt;/h3&gt;

&lt;p&gt;In your SQL file, use placeholders for the parameters you want to pass. The syntax for placeholders depends on your database engine. For PostgreSQL, use the positional placeholders &lt;code&gt;$1&lt;/code&gt;, &lt;code&gt;$2&lt;/code&gt;, etc.:&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="c1"&gt;-- prisma/sql/getUsersByAge.sql&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When using the generated function in your TypeScript code, pass the arguments as additional parameters to &lt;code&gt;$queryRawTyped&lt;/code&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&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;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUsersByAge&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;@prisma/client/sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&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;PrismaClient&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;minAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;users&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;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$queryRawTyped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getUsersByAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;minAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxAge&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;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example: Passing Array Arguments
&lt;/h3&gt;

&lt;p&gt;TypedSQL supports passing arrays as arguments for PostgreSQL. Use PostgreSQL's &lt;code&gt;ANY&lt;/code&gt; operator with an array parameter:&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="c1"&gt;-- prisma/sql/getUsersByIds.sql&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&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="k"&gt;ANY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&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;p&gt;In your TypeScript code:&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaClient&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;@prisma/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getUsersByIds&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;@prisma/client/sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prisma&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;PrismaClient&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;userIds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;users&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;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$queryRawTyped&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;getUsersByIds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userIds&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;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Defining Argument Types in SQL Files
&lt;/h2&gt;

&lt;p&gt;You can define the types of arguments directly in your SQL files using specific comments. This enhances type safety and ensures that the TypeScript client is fully aware of the types being passed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Typing Arguments
&lt;/h3&gt;

&lt;p&gt;Add the following comments to define the types:&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="c1"&gt;-- @param {Int} $1:minAge The minimum age of the user&lt;/span&gt;
&lt;span class="c1"&gt;-- @param {Int} $2:maxAge The maximum age of the user&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The format is consistent across all supported database engines and ensures that your TypeScript code accurately reflects the SQL query structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pros and Cons of Using TypedSQL
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pros
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Type Safety&lt;/strong&gt;: TypedSQL provides strong type safety for raw SQL queries, reducing the risk of runtime errors and ensuring consistent data handling.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrated DX&lt;/strong&gt;: By integrating with Prisma, TypedSQL allows you to write complex SQL queries while still benefiting from Prisma’s developer tools, like autocomplete and type inference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reusable Queries&lt;/strong&gt;: TypedSQL encourages the reuse of SQL queries across your application, making it easier to maintain and update your codebase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Protection Against SQL Injection&lt;/strong&gt;: By using parameterized queries, TypedSQL helps protect your application against SQL injection attacks, which are a common security vulnerability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better Performance for Complex Queries&lt;/strong&gt;: TypedSQL allows you to execute more complex and efficient SQL queries directly within Prisma, bypassing some of the limitations of Prisma’s query builder.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Cons
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Limited Dynamic SQL Support&lt;/strong&gt;: TypedSQL does not natively support constructing SQL queries with dynamically added columns. For such cases, you need to fall back to &lt;code&gt;$queryRaw&lt;/code&gt; or &lt;code&gt;$executeRaw&lt;/code&gt;, which means losing type safety.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Increased Complexity&lt;/strong&gt;: Using raw SQL, even with type safety, adds a layer of complexity to your codebase, especially if your team is more familiar with Prisma’s query builder syntax.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;: Developers need to be comfortable with both SQL and Prisma’s TypeScript client to use TypedSQL effectively. This might require additional learning for some team members.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dependency on Preview Features&lt;/strong&gt;: TypedSQL is currently a preview feature, meaning it’s not yet fully stable and might undergo breaking changes in future releases.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Full ORM Benefits&lt;/strong&gt;: When using TypedSQL, you miss out on some of the abstractions and conveniences that Prisma’s ORM provides, such as automatic relation handling and query optimization.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;TypedSQL is a powerful tool in Prisma’s ecosystem that bridges the gap between raw SQL and type-safe query construction. It offers the flexibility of raw SQL with the benefits of Prisma’s TypeScript client, making it ideal for scenarios where you need fine-grained control over your database queries.&lt;/p&gt;

&lt;p&gt;However, it’s important to weigh the pros and cons before adopting TypedSQL in your project. While it offers many advantages, particularly in terms of type safety and query performance, it also introduces complexity and requires a good understanding of SQL.&lt;/p&gt;

&lt;p&gt;By following the steps outlined in this guide, you can start using TypedSQL in your Prisma projects, writing more complex queries while maintaining the benefits of Prisma’s type-safe client.&lt;/p&gt;

</description>
      <category>typedsql</category>
      <category>prisma</category>
      <category>typesafe</category>
      <category>sql</category>
    </item>
    <item>
      <title>🚀3 Important Rules for Naming Variables in Excellent Code</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Sun, 17 Mar 2024 20:38:03 +0000</pubDate>
      <link>https://dev.to/fahimahammed/3-important-rules-for-naming-variables-in-excellent-code-f18</link>
      <guid>https://dev.to/fahimahammed/3-important-rules-for-naming-variables-in-excellent-code-f18</guid>
      <description>&lt;p&gt;Good variable names are just as important as clear function names for making code easy to understand. Here are 3 simple rules to make your variable names better:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Meaningful Names:&lt;/strong&gt; Replace generic names (like temp or x, y, x) with names that reflect their purpose.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ tempData&lt;br&gt;&lt;br&gt;
✅ customerOrder&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Descriptive Naming:&lt;/strong&gt; Use descriptive terms that explain the content of the variable.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ isSomething (unclear what "something" is)&lt;br&gt;
✅ isUserLoggedIn (clear and concise)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Case Consistency&lt;/strong&gt;: Pick a case convention (snake_case, camelCase) and stick to it throughout your codebase.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snake Case&lt;/strong&gt;: Lowercase letters with underscores for separation (e.g., total_price)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Camel Case&lt;/strong&gt;: Lowercase with the first letter of each word capitalized (e.g., totalPrice)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bonus Tip:&lt;/strong&gt;  Consider adding prefixes or suffixes for specific variable types (e.g., strFirstName, intEmployeeID).&lt;/p&gt;

&lt;p&gt;By following these principles, your variables become self-documenting, improving code readability and maintainability for yourself and your fellow developers.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Consistent naming across functions and variables is key!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>coding</category>
      <category>variable</category>
      <category>cleancode</category>
      <category>variablenaming</category>
    </item>
    <item>
      <title>GraphQL vs tRPC: Picking the Best Fit for Your Project</title>
      <dc:creator>Fahim Ahammed Firoz</dc:creator>
      <pubDate>Sat, 28 Oct 2023 19:33:21 +0000</pubDate>
      <link>https://dev.to/fahimahammed/graphql-vs-trpc-picking-the-best-fit-for-your-project-4b97</link>
      <guid>https://dev.to/fahimahammed/graphql-vs-trpc-picking-the-best-fit-for-your-project-4b97</guid>
      <description>&lt;p&gt;&lt;strong&gt;GraphQL *&lt;em&gt;এর সাথে বর্তমান সময়ে **tRPC *&lt;/em&gt;নামে একটি টেকনোলজির নাম বেশি শোনা যাচ্ছে।  এটি একটি **remote procedure call (RPC) framework&lt;/strong&gt; যা বিশেষভাবে TypeScript এর জন্য ডিজাইন করা হয়েছে। এটিতে ক্লায়েন্ট সাইট থেকেই সার্ভার ডিফাইন ফাংশন কল করা যায়। tRPC বেশ first এবং তুলনামূলক ব্যবহার করা সহজ। এছাড়াও এর এমন কিছু features রয়েছে যার জন্য এটিকে &lt;strong&gt;microservices-based applications&lt;/strong&gt; তৈরির জন্য আদর্শ বলা যেতে পারে। &lt;/p&gt;

&lt;p&gt;&lt;em&gt;কি!! এই কথাটুকু শুনে graphql শেখা বাদ দিয়ে tRPC শিখবেন? নাকি কনফিউশনে পড়ে গেলেন কোনটি শেখা ভালো হবে? আবার এমনটিও মনে হতে পারে যে পুরান পাগলে ভাত পায় না নতুন পাগলের আমদানি।&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;তাহলে আগে এই পাগল দ্বয়ের উদয় হলো কোন সময়ে সেটি জানার চেষ্টা করি। ২০১২ সালে মার্ক সাইমন, জোসেফ উইলিয়ামস এবং জোয়েল ওয়াল্টন GraphQL তৈরি করেছিল এবং ২০১৫ সালে এটির প্রথম ভার্সন রিলিজ করা হয়েছিল। ২০১৬ সাল থেকে এটি বেশ জনপ্রিয় হতে থাকে এবং facebook, Google, Microsoft এর মতো বড় বড় কোম্পানি এটি ব্যবহার করা শুরু করে। &lt;/p&gt;

&lt;p&gt;অন্যদিকে, ২০২০ সালে ডেভিড ক্রাউন tRPC নামে একটি RPC framework তৈরি করে এবং ২০২১ সালে tRPC 1.0 রিলিজ করা হয়েছিল। ২০২২ সাল থেকে এটি বেশ জনপ্রিয় হতে শুরু করে। &lt;/p&gt;

&lt;p&gt;_GraphQL এবং tRPC দুটিই API তৈরির জন্য ব্যবহৃত টেকনোলজি। তবে এদের মধ্যে কিছু গুরুত্বপূর্ণ পার্থক্য রয়েছে। যেমনঃ _&lt;br&gt;
GraphQL একটি query language, &amp;amp; tRPC একটি RPC Framework. এর মানে হল যে GraphQL ব্যবহার করে, আপনি একটি API তৈরি করতে পারেন যা ক্লায়েন্টকে সার্ভার থেকে data access করতে দেয়। অন্যদিকে, tRPC ব্যবহার করে, আপনি একটি API তৈরি করতে পারেন যা ক্লায়েন্ট এবং সার্ভার মধ্যে data transfer করতে দেয়। পার্ফমেন্সের দিক থেকে tRPC কিছুটা এগিয়ে থাকলেও GraphQL flexibility এর দিক থেকে এগিয়ে রয়েছে। GraphQL API তৈরিতে বিভিন্ন ধরনের ল্যাগুয়েজ ব্যবহার করা যায়, কিন্তু tRPC শুধু মাত্র TypeScript এর জন্য ডিজাইন করা। &lt;/p&gt;

&lt;p&gt;দুটিই বেশ ভালো টেকনোলজি এবং দুটিরই ভালো সুবিধা রয়েছে আবার কিছু লিমিটেশনও রয়েছে। তাহলে কোন ধরনের প্রজেক্টে কোনটি use করা উচিত? &lt;/p&gt;

&lt;p&gt;আপনি যদি একটি powerful &amp;amp; flexible API তৈরি করতে চান যার মাধ্যমে ক্লায়েন্ট থেকে স্পেসিফিক ডেটার জন্য রিকোয়েস্ট করতে পারবেন তাহলে GraphQL ভালো পছন্দ হতে পারে। যেমনঃ Social Media API, Content Management System (CMS), Data Analytics API. &lt;/p&gt;

&lt;p&gt;আবার অন্যদিকে, আপনি যদি simple &amp;amp; ব্যবহার করা সহজ এমন API  তৈরি করতে চান যা data transfer করতে পারবে, তাহলে tRPC ভালো পছন্দ হতে পারে। tRPC মূলত microservice based application এর জন্য ডিজাইন করা হয়েছে। এছাড়াও real-time chat application, gaming application তৈরিতেও এটি ব্যবহার করা যেতে পারে। &lt;/p&gt;

&lt;p&gt;সবশেষে বলতে পারি যে, GraphQL এবং tRPC উভয়ই শক্তিশালী এবং কার্যকর টেকনোলজি। দুটিরই বেশ জনপ্রিয়তা এবং প্রয়োজনীয়তা রয়েছে। এখন আপনার কাজের ধরন এবং প্রয়োজনীয়তার উপর নির্ভর করছে আপনি আপনার প্রজেক্টে/এপ্লিকেশনে কোনটি ব্যবহার করবেন।&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_References: _&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.logrocket.com/trpc-vs-graphql-better-projects/" rel="noopener noreferrer"&gt;https://blog.logrocket.com/trpc-vs-graphql-better-projects/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://graphql.org/" rel="noopener noreferrer"&gt;https://graphql.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://trpc.io/" rel="noopener noreferrer"&gt;https://trpc.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cleancommit.io/blog/trpc-vs-graphql-how-to-choose-the-best-option-for-your-next-project/" rel="noopener noreferrer"&gt;https://cleancommit.io/blog/trpc-vs-graphql-how-to-choose-the-best-option-for-your-next-project/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>graphql</category>
      <category>trpc</category>
      <category>api</category>
    </item>
  </channel>
</rss>
