Close Menu
Soshace Digital Blog

    Subscribe to Updates

    Get The Latest News, Updates, And Amazing Offers

    What's Hot
    Programming

    24. Уроки Node.js. Чтение параметров из командной строки и окружения.

    Entrepreneurship

    Three Latest Books Every Entrepreneur Should Read | Best Business Books

    JavaScript

    The Ultimate Guide to Drag and Drop Image Uploading with Pure JavaScript

    Important Pages:
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Today's Picks:
    • Scaling Success: Monitoring Indexation of Programmatic SEO Content
    • Leveraging Influencers: Key Drivers in New Product Launches
    • How Privacy-First Marketing Will Transform the Industry Landscape
    • The Impact of Social Proof on Thought Leadership Marketing
    • Balancing Value-Driven Content and Promotional Messaging Strategies
    • Top Influencer Marketing Platforms to Explore in 2025
    • Emerging Trends in Marketing Automation and AI Tools for 2023
    • Strategies to Mitigate Duplicate Content in Programmatic SEO
    Wednesday, September 10
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Soshace Digital Blog
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Services
    • SaaS & Tech

      Maximizing Efficiency: How SaaS Lowers IT Infrastructure Costs

      August 27, 2025

      Navigating Tomorrow: Innovations Shaping the Future of SaaS

      August 27, 2025

      Maximizing Impact: Strategies for SaaS & Technology Marketing

      August 27, 2025
    • AI & Automation

      Enhancing Customer Feedback Analysis Through AI Innovations

      August 27, 2025

      Navigating the Impact of AI on SEO and Search Rankings

      August 27, 2025

      5 Automation Hacks Every Home Service Business Needs to Know

      May 3, 2025
    • Finance & Fintech

      Critical Missteps in Finance Marketing: What to Avoid

      August 27, 2025

      Analyzing Future Fintech Marketing Trends: Insights Ahead

      August 27, 2025

      Navigating the Complex Landscape of Finance and Fintech Marketing

      August 27, 2025
    • Legal & Compliance

      Exploring Thought Leadership’s Impact on Legal Marketing

      August 27, 2025

      Maximizing LinkedIn: Strategies for Legal and Compliance Marketing

      August 27, 2025

      Why Transparency Matters in Legal Advertising Practices

      August 27, 2025
    • Medical Marketing

      Enhancing Online Reputation Management in Hospitals: A Guide

      August 27, 2025

      Analyzing Emerging Trends in Health and Medical Marketing

      August 27, 2025

      Exploring Innovative Content Ideas for Wellness Blogs and Clinics

      August 27, 2025
    • E-commerce & Retail

      Strategic Seasonal Campaign Concepts for Online and Retail Markets

      August 27, 2025

      Emerging Trends in E-commerce and Retail Marketing Strategies

      August 27, 2025

      Maximizing Revenue: The Advantages of Affiliate Marketing for E-Commerce

      August 27, 2025
    • Influencer & Community

      Leveraging Influencers: Key Drivers in New Product Launches

      August 27, 2025

      Top Influencer Marketing Platforms to Explore in 2025

      August 27, 2025

      Key Strategies for Successful Influencer Partnership Negotiations

      August 27, 2025
    • Content & Leadership

      The Impact of Social Proof on Thought Leadership Marketing

      August 27, 2025

      Balancing Value-Driven Content and Promotional Messaging Strategies

      August 27, 2025

      Analyzing Storytelling’s Impact on Content Marketing Effectiveness

      August 27, 2025
    • SEO & Analytics

      Scaling Success: Monitoring Indexation of Programmatic SEO Content

      August 27, 2025

      Strategies to Mitigate Duplicate Content in Programmatic SEO

      August 27, 2025

      Effective Data Visualization Techniques for SEO Reporting

      August 27, 2025
    • Marketing Trends

      How Privacy-First Marketing Will Transform the Industry Landscape

      August 27, 2025

      Emerging Trends in Marketing Automation and AI Tools for 2023

      August 27, 2025

      Maximizing ROI: Key Trends in Paid Social Advertising

      August 27, 2025
    Soshace Digital Blog
    Blog / JavaScript / Node.js / Protecting Your API from Brute Forcing By Rate Limiting in NodeJS
    Node.js

    Protecting Your API from Brute Forcing By Rate Limiting in NodeJS

    bradstarartBy bradstarartJuly 16, 2020No Comments14 Mins Read
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    Protecting Your API from Brute Forcing By Rate Limiting in NodeJS
    Protecting Your API from Brute Forcing By Rate Limiting in NodeJS
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link
    Protecting Your API from Brute Forcing By Rate Limiting in NodeJS
    Protecting Your API from Brute Forcing By Rate Limiting in NodeJS

    Brute forcing is one of the oldest tricks in the black hat hacker’s handbook. The most predominant way of performing a brute force attack is configuring a set of predetermined values, making requests to a server (in this case, your API) and analysing the response.

    For efficiency’s sake, an attacker would probably prefer a dictionary attack. A ‘dictionary’ is a gigantic list of passwords (these can simply be commonly-used passwords or perhaps values amalgamated from past data breaches).

    If the attacker has reason to believe traditional brute force attacks might be more efficient, however, they might use a more traditional (and far less efficient) approach – testing random classes of characters – a random mix of alphanumeric and special characters in the hopes they get lucky.

    If you have a login or registration form on your website, you’re already a target. No login form should ever be released to the wild without at least some protection in place.

    In this article, we cover exactly that – the basics of what rate limiting is and how it can be implemented in NodeJS and how it adds an extra layer security to your API.

    What is rate limiting

    Rate limiting is a technique used to control the flow of data to and from a server by limiting the number of interactions a user can have with your API. This prevents a single user from using up too many resources (either accidentally or on purpose).

    For example, your SaaS messaging app could limit unregistered users to 1,000 API requests per day. Any further requests are denied.

    In order to control this flow of data this way, we first need to define criteria for how to prevent excessive requests from reaching our business logic code. How do we identify who needs to be blocked? Commonly-used identifiers are:

    1. A user id: a user id would be most effective for a service that authorizes users and assigns them unique identifiers. Perhaps your service has fixed limits that have prior been communicated to the end user.This would also be a good choice if your service doesn’t collect user data like IP addresses and location data. Note that any unique value can serve as a ‘user id’, including private/secret keys and usernames.
    2. IP address: this method works best if you don’t have any other way to uniquely identify a user. While it works very well in some cases, you should be careful not to inadvertently block users with shared IP addresses.
    3. Geolocation: most malware attacks are known to originate from a handful of countries. With rate limiting, these countries can be isolated and blocked without affecting users from other regions.

    Under the hood: rate-limiting algorithms

    There are several algorithms that can be used to rate limit user interactions, each of which has its unique drawbacks and advantages.

    Leaky bucket algorithm

    There are two different ways the leaky bucket algorithm is commonly described: as a queue or as a metre, but we won’t get into the specifics of the latter. Instead, let’s consider a bucket filled to the brim with water but has a hole at the bottom.

    Important characteristics of this bucket to note are:

    1. The water leaks at a (reasonably) constant rate.
    2. If a large amount of water is added to the bucket at once, the water overflows. However, this doesn’t affect the leak rate.
    3. If the average rate of pouring water into the bucket is larger than the leak rate, the bucket will overflow. Again, this doesn’t affect the leak rate.

    The leaky bucket algorithm borrows from this analogy.

    When the API gets a request, it’s added to a queue, and at regular intervals, the requests are processed. If there are too many requests, the last ones in the queue will be ignored. It’s essentially a FIFO (first-in first-out) queue.

    One great advantage this algorithm offers is that it can smooth out processing of requests to an approximately average rate. It’s also easy to implement on a single server or load balancer and is quite memory efficient thanks to the limited queue size.

    The leaky bucket algorithm does have its disadvantages, though. For instance, a sudden burst of legitimate traffic means newer requests are going to be starved of attention since the queue is filled up. This will have the unintended consequence of making the user experience rather slow.

    Token bucket algorithm

    In the token bucket algorithm, we create a ‘bucket’ for every user and fill it with a certain number of ‘tokens’. Every time a user makes a request to our API, we subtract some tokens from their bucket and update it with a timestamp indicating when the update happened.

    After a fixed period of time (referred to as the window), the bucket is refilled with tokens, essentially resetting a user’s usage back to zero

    A major advantage of the token bucket algorithm is that it accounts for burstiness. It’s not adversely affected by a sudden burst in traffic the same way the leaky bucket algorithm is.

    For the sake of conciseness, this article won’t cover the fixed window, sliding window and the sliding window log algorithms. While simple to implement, they tend to be very inefficient. However, Figma covers them in-depth with the added advantage of some practical considerations before shipping to production.

    Read More:  Building a Full Stack Application using RedwoodJS

    Preventing endpoint brute forcing in NodeJS

    Not all endpoints in your app need to be protected against brute forcing. For example, a private endpoint protected with a JWT token for internal use isn’t the highest-target priority. Adding some form of rate limiting might be highly advantageous in case of a rogue actor, however.

    First, let’s set up a dummy project with express

    npx --package express-generator express

    We could write the whole algorithm ourselves, but there’s no need to re-invent the wheel. We’ll rely on express-brute for our simple implementation.

    npm install redis ms express-brute express-brute-redis --save
    • redis – our in-memory cache
    • ms – helps to convert units to milliseconds
    • express-brute – node implementation of rate limiting algorithm

    Here is our folder structure (ignoring a bunch of files that express included but we don’t need)

    .
    ├── app.js
    ├── bin
    │   └── www
    ├── middleware
    │   ├── index.js
    │   └── rateLimiter.js
    ├── package.json
    ├── package-lock.json
    ├── routes
    │   └──index.js
    

    In the middleware folder,

    //index.js
    module.exports.limiter = require('./rateLimiter');
    
    //rateLimiter.js
    const ms = require('ms');
    const redis = require('redis');
    const ExpressBrute = require('express-brute'),
        RedisStore = require('express-brute-redis');
    
    const handleStoreError = function (error) {
        console.error(error); // log this error so we can figure out what went wrong
        // cause node to exit, hopefully restarting the process fixes the problem
        throw {
            message: error.message,
            parent: error.parent
        };
    };
    
    const redisClient = redis.createClient(); // Create a new
    
    redisClient.on('connect', function () {
        console.log("Connected to redis")
    });
    
    redisClient.on('error', function () {
        console.log("Redis crashed.")
    
    })
    
    const store = new RedisStore({
        client: redisClient,
    });
    
    module.exports = new ExpressBrute(store, {
        freeRetries: 3,
        minWait: ms('10s'), 
        maxWait: ms('1min'),
        handleStoreError
    });
    
    

    Brute forcing is one of the oldest tricks in the black hat hacker’s handbook. The most predominant way of performing a brute force attack is configuring a set of predetermined values, making requests to a server (in this case, your API) and analysing the response.

    For efficiency’s sake, an attacker would probably prefer a dictionary attack. A ‘dictionary’ is a gigantic list of passwords (these can simply be commonly-used passwords or perhaps values amalgamated from past data breaches).

    If the attacker has reason to believe traditional brute force attacks might be more efficient, however, they might use a more traditional (and far less efficient) approach – testing random classes of characters – a random mix of alphanumeric and special characters in the hopes they get lucky.

    If you have a login or registration form on your website, you’re already a target. No login form should ever be released to the wild without at least some protection in place.

    In this article, we cover exactly that – the basics of what rate limiting is and how it can be implemented in NodeJS and how it adds an extra layer security to your API.

    What is rate limiting

    Rate limiting is a technique used to control the flow of data to and from a server by limiting the number of interactions a user can have with your API. This prevents a single user from using up too many resources (either accidentally or on purpose).

    For example, your SaaS messaging app could limit unregistered users to 1,000 API requests per day. Any further requests are denied.

    In order to control this flow of data this way, we first need to define criteria for how to prevent excessive requests from reaching our business logic code. How do we identify who needs to be blocked? Commonly-used identifiers are:

    1. A user id: a user id would be most effective for a service that authorizes users and assigns them unique identifiers. Perhaps your service has fixed limits that have prior been communicated to the end user.This would also be a good choice if your service doesn’t collect user data like IP addresses and location data. Note that any unique value can serve as a ‘user id’, including private/secret keys and usernames.
    2. IP address: this method works best if you don’t have any other way to uniquely identify a user. While it works very well in some cases, you should be careful not to inadvertently block users with shared IP addresses.
    3. Geolocation: most malware attacks are known to originate from a handful of countries. With rate limiting, these countries can be isolated and blocked without affecting users from other regions.

    Under the hood: rate-limiting algorithms

    There are several algorithms that can be used to rate limit user interactions, each of which has its unique drawbacks and advantages.

    Leaky bucket algorithm

    There are two different ways the leaky bucket algorithm is commonly described: as a queue or as a metre, but we won’t get into the specifics of the latter. Instead, let’s consider a bucket filled to the brim with water but has a hole at the bottom.

    Important characteristics of this bucket to note are:

    1. The water leaks at a (reasonably) constant rate.
    2. If a large amount of water is added to the bucket at once, the water overflows. However, this doesn’t affect the leak rate.
    3. If the average rate of pouring water into the bucket is larger than the leak rate, the bucket will overflow. Again, this doesn’t affect the leak rate.

    The leaky bucket algorithm borrows from this analogy.

    When the API gets a request, it’s added to a queue, and at regular intervals, the requests are processed. If there are too many requests, the last ones in the queue will be ignored. It’s essentially a FIFO (first-in first-out) queue.

    Read More:  Server-Side Rendering with Vue.js and Nuxt.js

    One great advantage this algorithm offers is that it can smooth out processing of requests to an approximately average rate. It’s also easy to implement on a single server or load balancer and is quite memory efficient thanks to the limited queue size.

    The leaky bucket algorithm does have its disadvantages, though. For instance, a sudden burst of legitimate traffic means newer requests are going to be starved of attention since the queue is filled up. This will have the unintended consequence of making the user experience rather slow.

    Token bucket algorithm

    In the token bucket algorithm, we create a ‘bucket’ for every user and fill it with a certain number of ‘tokens’. Every time a user makes a request to our API, we subtract some tokens from their bucket and update it with a timestamp indicating when the update happened.

    After a fixed period of time (referred to as the window), the bucket is refilled with tokens, essentially resetting a user’s usage back to zero

    A major advantage of the token bucket algorithm is that it accounts for burstiness. It’s not adversely affected by a sudden burst in traffic the same way the leaky bucket algorithm is.

    For the sake of conciseness, this article won’t cover the fixed window, sliding window and the sliding window log algorithms. While simple to implement, they tend to be very inefficient. However, Figma covers them in-depth with the added advantage of some practical considerations before shipping to production.

    Preventing endpoint brute forcing in NodeJS

    Not all endpoints in your app need to be protected against brute forcing. For example, a private endpoint protected with a JWT token for internal use isn’t the highest-target priority. Adding some form of rate limiting might be highly advantageous in case of a rogue actor, however.

    First, let’s set up a dummy project with express

    npx --package express-generator express

    We could write the whole algorithm ourselves, but there’s no need to re-invent the wheel. We’ll rely on express-brute for our simple implementation.

    npm install redis ms express-brute express-brute-redis --save
    • redis – our in-memory cache
    • ms – helps to convert units to milliseconds
    • express-brute – node implementation of rate limiting algorithm

    Here is our folder structure (ignoring a bunch of files that express included but we don’t need)

    .
    ├── app.js
    ├── bin
    │   └── www
    ├── middleware
    │   ├── index.js
    │   └── rateLimiter.js
    ├── package.json
    ├── package-lock.json
    ├── routes
    │   └──index.js
    

    In the middleware folder,

    //index.js
    module.exports.limiter = require('./rateLimiter');
    
    //rateLimiter.js
    const ms = require('ms');
    const redis = require('redis');
    const ExpressBrute = require('express-brute'),
        RedisStore = require('express-brute-redis');
    
    const handleStoreError = function (error) {
        console.error(error); // log this error so we can figure out what went wrong
        // cause node to exit, hopefully restarting the process fixes the problem
        throw {
            message: error.message,
            parent: error.parent
        };
    };
    
    const redisClient = redis.createClient(); // Create a new
    
    redisClient.on('connect', function () {
        console.log("Connected to redis")
    });
    
    redisClient.on('error', function () {
        console.log("Redis crashed.")
    
    })
    
    const store = new RedisStore({
        client: redisClient,
    });
    
    module.exports = new ExpressBrute(store, {
        freeRetries: 3,
        minWait: ms('10s'), 
        maxWait: ms('1min'),
        handleStoreError
    });
    
    
    • freeRetries – the number of tries a user has before they are ‘blacklisted’
    • minWait – the time a user has to wait when they run out of retries for the first time
    • maxWait – the maximum amount of time a user will have to wait
    • handleStoreError – handle the error if anything goes wrong with Redis

    In pseudocode:

    • A can incorrectly enter their username/password combination three times (freeRetries).
    • The first time they run out of retries, the user will wait for 10 seconds before being able to try again.
    • If they enter their username/password incorrectly three times again they will have to wait a little longer than 10 seconds (the exact time is determined by the library)
    • The maximum wait time is 1 minute.
    • Another interesting way to think of the above code is ‘10 requests every 1 minute’ (minWait every maxWait). However, this only works if your minWait is in seconds.

    Voila! We’re done!

    How does this look in practice? (For this test, I set the following arbitrary values freeRetries=1 minWait=1s, maxWait=10s)

    When we hit the API for the first time, everything goes smoothly:

    Brute force prevention nodejs rate limiter succeeded
    Brute force prevention nodejs rate limiter succeeded

    If we try again within 10 seconds:

    Brute force prevention nodejs rate limiter blocked
    Brute force prevention nodejs rate limiter blocked

    Notice the Retry-After header. This tells the client they are allowed to try again in ‘x seconds’ (9 seconds in this case).

    If you wanted to change the header to something like ‘X-Rate-Limit’, use the ‘failAction’ method in the library to specify a custom header.

    For the github code: https://github.com/Bradleykingz/node-rate-limiter-tutorial

    Conclusion

    In this article, we covered the basics of rate limiting and how it can be used to secure your API against malicious actors. It’s important to note, however that rate limiting isn’t the only way to mitigate brute force attacks and can be, in fact, downright useless against a determined attacker.

    The methods of attack are often complex and varied, as described by the Open Web Application Security Project (OWASP). As such, rate limiting isn’t a  silver bullet for all your anti-brute-forcing needs.

    For a more detailed overview of the topic and the various methods you can use to keep your services safe, read this other guide by OWASP.

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    bradstarart

      Related Posts

      An Introduction to Clustering in Node.js

      March 26, 2024

      Server-Side Rendering with Vue.js and Nuxt.js

      February 26, 2024

      Mastering N-API and Native Modules in Node.js

      February 13, 2024
      Leave A Reply Cancel Reply

      You must be logged in to post a comment.

      Stay In Touch
      • Facebook
      • Twitter
      • Pinterest
      • Instagram
      • YouTube
      • Vimeo
      Don't Miss
      Beginners July 29, 2019

      Public Speaking for Developers Demystified: Tips & Tricks

      In this piece, we’ll suggest the tips and techniques to help you master the art of public speaking and prepare for your next talk, be it at a tech conference or a meetup.

      10 Sorting Algorithms Interview Questions: Theory and Practice for 2019

      June 7, 2019

      Navigating Tomorrow: Innovations Shaping the Future of SaaS

      August 27, 2025

      Working the Agile Way: Lean and Kanban

      May 29, 2019

      Categories

      • AI & Automation
      • Angular
      • ASP.NET
      • AWS
      • B2B Leads
      • Beginners
      • Blogs
      • Business Growth
      • Case Studies
      • Comics
      • Consultation
      • Content & Leadership
      • CSS
      • Development
      • Django
      • E-commerce & Retail
      • Entrepreneurs
      • Entrepreneurship
      • Events
      • Express.js
      • Facebook Ads
      • Finance & Fintech
      • Flask
      • Flutter
      • Franchising
      • Funnel Strategy
      • Git
      • GraphQL
      • Home Services Marketing
      • Influencer & Community
      • Interview
      • Java
      • Java Spring
      • JavaScript
      • Job
      • Laravel
      • Lead Generation
      • Legal & Compliance
      • LinkedIn
      • Machine Learning
      • Marketing Trends
      • Medical Marketing
      • MSP Lead Generation
      • MSP Marketing
      • NestJS
      • Next.js
      • Node.js
      • Node.js Lessons
      • Paid Advertising
      • PHP
      • Podcasts
      • POS Tutorial
      • Programming
      • Programming
      • Python
      • React
      • React Lessons
      • React Native
      • React Native Lessons
      • Recruitment
      • Remote Job
      • SaaS & Tech
      • SEO & Analytics
      • Soshace
      • Startups
      • Swarm Intelligence
      • Tips
      • Trends
      • Vue
      • Wiki
      • WordPress
      Top Posts

      Ultimate Onboarding Checklist for Web Developers (Bonus: Onboarding Checklist for Freelancers)

      Remote Job July 15, 2019

      Building React Components Using Children Props and Context API

      JavaScript August 22, 2019

      Уроки React . Урок 9

      Programming October 7, 2016

      Maximizing Hiring Efficiency: A Guide to Recruitment Software

      Recruitment November 28, 2024

      Subscribe to Updates

      Get The Latest News, Updates, And Amazing Offers

      About Us
      About Us

      Soshace Digital delivers comprehensive web design and development solutions tailored to your business objectives. Your website will be meticulously designed and developed by our team of seasoned professionals, who combine creative expertise with technical excellence to transform your vision into a high-impact, user-centric digital experience that elevates your brand and drives measurable results.

      7901 4th St N, Suite 28690
      Saint Petersburg, FL 33702-4305
      Phone: 1(877)SOSHACE

      Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
      Our Picks
      JavaScript

      Interoperability between Ethereum, Binance Smart Chain, and other blockchain platforms using Node.js

      Influencer & Community

      Key Strategies for Successful Influencer Partnership Negotiations

      Programming

      Code Style

      Most Popular

      Уроки React. Урок 6.

      Programming

      14. Node.js Lessons. Script Debugging pt 1.

      Programming

      Conducting Effective Post-Project Evaluations: A Guide

      JavaScript
      © 2025 Soshace Digital.
      • Home
      • About
      • Services
      • Contact Us
      • Privacy Policy
      • Terms & Conditions

      Type above and press Enter to search. Press Esc to cancel.