Skip to content

DDPRateLimiter

Customize rate limiting for methods and subscriptions to avoid a high load of WebSocket messages in your app.

Galaxy (Meteor hosting) offers additional App Protection, read more and try it with our free 30-day trial.

By default, DDPRateLimiter is configured with a single rule. This rule limits login attempts, new user creation, and password resets to 5 attempts every 10 seconds per connection. It can be removed by calling Accounts.removeDefaultRateLimit().

To use DDPRateLimiter for modifying the default rate-limiting rules, add the ddp-rate-limiter package to your project in your terminal:

bash
meteor add ddp-rate-limiter

DDPRateLimiter.addRule

Server only

Summary:

Add a rule that matches against a stream of events describing method or subscription attempts. Each event is an object with the following properties:

  • type: Either "method" or "subscription"
  • name: The name of the method or subscription being called
  • userId: The user ID attempting the method or subscription
  • connectionId: A string representing the user's DDP connection
  • clientAddress: The IP address of the user

Returns unique ruleId that can be passed to removeRule and setErrorMessageOnRule

Arguments:

Source code
NameTypeDescriptionRequired
matcherObject

Matchers specify which events are counted towards a rate limit. A matcher is an object that has a subset of the same properties as the event objects described above. Each value in a matcher object is one of the following:

  • a string: for the event to satisfy the matcher, this value must be equal to the value of the same property in the event object

  • a function: for the event to satisfy the matcher, the function must evaluate to true when passed the value of the same property in the event object

Here's how events are counted: Each event that satisfies the matcher's filter is mapped to a bucket. Buckets are uniquely determined by the event object's values for all properties present in both the matcher and event objects.

Yes
numRequestsnumber

number of requests allowed per time interval. Default = 10.

Yes
timeIntervalnumber

time interval in milliseconds after which rule's counters are reset. Default = 1000.

Yes
callbackfunction

function to be called after a rule is executed.

Yes

Custom rules can be added by calling DDPRateLimiter.addRule. The rate limiter is called on every method and subscription invocation.

A rate limit is reached when a bucket has surpassed the rule's predefined capacity, at which point errors will be returned for that input until the buckets are reset. Buckets are regularly reset after the end of a time interval.

Here's example of defining a rule and adding it into the DDPRateLimiter:

js
// Define a rule that matches login attempts by non-admin users.
const loginRule = {
  userId(userId) {
    const user = Meteor.users.findOne(userId);
    return user && user.type !== 'admin';
  },

  type: 'method',
  name: 'login'
};

// Add the rule, allowing up to 5 messages every 1000 milliseconds.
DDPRateLimiter.addRule(loginRule, 5, 1000);

DDPRateLimiter.removeRule

Server only

Summary:

Removes the specified rule from the rate limiter. If rule had hit a rate limit, that limit is removed as well.

Arguments:

Source code
NameTypeDescriptionRequired
idstring

'ruleId' returned from addRule

Yes
js
import { DDPRateLimiter } from "meteor/ddp-rate-limiter";

/** @returns {boolean} */
const result = DDPRateLimiter.removeRule();
  "id"
);

DDPRateLimiter.setErrorMessage

Server only

Summary:

Set error message text when method or subscription rate limit exceeded.

Arguments:

Source code
NameTypeDescriptionRequired
messagestring or function

Functions are passed in an object with a timeToReset field that specifies the number of milliseconds until the next method or subscription is allowed to run. The function must return a string of the error message.

Yes
js
import { DDPRateLimiter } from "meteor/ddp-rate-limiter";


const result = DDPRateLimiter.setErrorMessage();
  "message"
);

DDPRateLimiter.setErrorMessageOnRule

Server only

Summary:

Set error message text when method or subscription rate limit exceeded for a specific rule.

Arguments:

Source code
NameTypeDescriptionRequired
ruleIdstring

The ruleId returned from addRule

Yes
messagestring or function

Functions are passed in an object with a timeToReset field that specifies the number of milliseconds until the next method or subscription is allowed to run. The function must return a string of the error message.

Yes
js
import { DDPRateLimiter } from "meteor/ddp-rate-limiter";


const result = DDPRateLimiter.setErrorMessageOnRule();
  "ruleId",
"message",
);

Allows developers to specify custom error messages for each rule instead of being limited to one global error message for every rule. It adds some clarity to what rules triggered which errors, allowing for better UX and also opens the door for i18nable error messages per rule instead of the default English error message.

Here is an example with a custom error message:

js
const setupGoogleAuthenticatorRule = {
  userId(userId) {
    const user = Meteor.users.findOne(userId);
    return user;
  },
  type: 'method',
  name: 'Users.setupGoogleAuthenticator',
};

// Add the rule, allowing up to 1 google auth setup message every 60 seconds
const ruleId = DDPRateLimiter.addRule(setupGoogleAuthenticatorRule, 1, 60000);
DDPRateLimiter.setErrorMessageOnRule(ruleId, function (data) {
  return `You have reached the maximum number of Google Authenticator attempts. Please try again in ${Math.ceil(data.timeToReset / 1000)} seconds.`;
});

Or a more simple approach:

js
const ruleId = DDPRateLimiter.addRule(setupGoogleAuthenticatorRule, 1, 60000);
DDPRateLimiter.setErrorMessageOnRule(ruleId, 'Example as a single string error message');