Global rate limits and throttling in Discourse

Discourse ships with 3 different global rate limits that can be configured by site admins.

Global per-ip rate limits

These limits apply to every unique IP address that hits the Discourse application. (files that are served directly from the filesystem or the CDN are excluded)

By default this rate limit is disabled, but we are considering enabling it out of the box.

DISCOURSE_MAX_REQS_PER_IP_MODE : default none, this rate limit does not apply out of the box yet. (other options are warn and warn+block)

DISCOURSE_MAX_REQS_PER_IP_PER_MINUTE: number of requests per IP per minute (default is 200)

DISCOURSE_MAX_REQS_PER_IP_PER_10_SECONDS: number of requests per IP per 10 seconds (default is 50)

DISCOURSE_MAX_ASSET_REQS_PER_IP_PER_10_SECONDS: number of asset (avatars/css) requests per IP per 10 seconds (default is 200)

DISCOURSE_MAX_REQS_RATE_LIMIT_ON_PRIVATE: should the rate limit apply to private IPs accessing Discourse? default is false.

User API rate limits

The mobile applications acquire a user API key per device to access Discourse on behalf of a user (using an open protocol). These API keys are very tightly limited.


Admin API rate limits

The administrative API keys can be generated via the page. These keys can operate on behalf of users, but require administrative privileges to generate. They are limited, but not as strictly as the user API keys.


Versions of Discourse prior to 1.9 did not include this limiting.

What should I do if I hit a rate limit and get throttled?

If you are consuming the API programmatically and receive back a 429 status code throttle reply you should respect it and slow down.

As an end user you should not really experience rate limits if you do, slow down. You could trigger it by opening 50 tabs real quick or doing something like that.

How do I amend these limits?

To amend the limits add the desired change into your app.yml file in the env section.

If you are hosted by Discourse contact


Just curious as to what the conversations were that made this a consideration… any specific examples or patterns that you’ve seen emerge from existing customers?

In general we believe that everything should be rate limited: Rate Limiting and Velocity Checking. The reason that global per-ip rate limits were added was because users were finding creative ways around the existing rate limits.

For example, opening a very large number of tabs all at once creates a huge number of concurrent requests to the server. If global rate limiting is disabled your server will be hit by all those requests at once. Limiting this to a reasonable number allows you to open many tabs still, but not too many that your server has to start queueing the requests.


Hi Sam,
I have a couple of usability queries around the data returned from the API.

When I looked at the data returned from the API a couple of weeks ago, the back of period only appears to be accessible via the text which explains why the limiting is in place.

{"errors":["We have a daily limit on how many times that action can be
taken. Please wait 10 seconds before trying

Is it possible to add a second error class (perhaps retry_delay or similar) which contains the number of seconds to back off as a separate field?

My second comment relates to the error pasted above - is it possible that ‘we have a daily limit’ is being used incorrectly, if I only need to wait another 10 seconds before I can try again? I’m guessing it should say “there is a limit on usage per X number seconds”.



Fixed …

And … fixed


Like lightning, thanks Sam!

I will try and test it in the next couple of days and see how I go.

1 Like

OK, will get it deployed a bit later today.

1 Like

Will it be possible to change this value from the admin panel? If these strict values are enabled by default and can not easily be changed by site admins, I fear I’ll have to do a really, really costly rewrite of the DiscourseMetrics backend.


no, sadly this is not planned, these settings are meant to be hard to amend. For hosting scenarios such as our hosting we are in control of this and not our customers.


Hi Sam,
Another query regarding the limits.

Is there an API endpoint we can query to proactively determine how many requests are permitted in a period of time?

There is not an API endpoint to check for number of requests left. The best method right now is to check the http status code for a 429 and then back off for the amount listed in the body of that response.


Hi Blake,

I was imaging something more proactive, for example:

  • I need to send 80 queries
  • I know i’m limited to something less than that
  • query to api.discourse/something
    -> oh, I can do 40 queries per minute
    -> better space my queries out over 2 minutes

Since there is nothing in that vein, I will simply rely on the 429 :slight_smile:

1 Like

Hi again,
I just spotted this response to a 429:

“You have performed this action too many times. Please wait 0 seconds before trying again.”

It smacks of off-by-one error somewhere - if it isn’t its a bit of an odd response.

1 Like

My guess is it’s a rounding error (please wait 0.4 seconds), but Sam would need to confirm.

1 Like

I think its more likely a rounding error. Will have a look at improving it so we pretend 1 if it is 0.1.


2 posts were split to a new topic: When rate limiting is hit return return a Retry-After header

Is there any way to change this setting? In app.yml maybe?

Is there any way to change this setting:

for a local installation on Mac OS following this guide?

It is set in config/discourse_defaults.conf. You should be able to set it as an environment variable when you start the rails server in development:


Loading development environment (Rails 5.2.2)
[1] pry(main)> GlobalSetting.max_admin_api_reqs_per_key_per_minute
=> 120
[2] pry(main)> 

It works! Thank you very much!