Skip to content

Commit bea87e7

Browse files
santicomp2014claude
andcommitted
Improve rate limits and add caching for shared-IP environments
Partners like bioRxiv/medRxiv make multiple unauthenticated search API calls per page load (2 groups x paginated at limit=50). In shared-IP environments (conferences, universities), all users share one rate limit bucket, causing 429s. Changes: - Bump general API rate limit from 4r/s burst=44 to 10r/s burst=200 - Bump badge rate limit from 1r/s burst=15 to 10r/s burst=100 - Add Cache-Control: public, max-age=60 on unauthenticated search responses and all badge responses (identical queries from shared-IP users now served from CloudFlare/browser cache) - Enable nginx JSON access logging for rate limit visibility - Increase rate limit zone memory from 1m to 2m (~16k users) Ref: product-backlog#1716 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 555633a commit bea87e7

File tree

6 files changed

+517
-9
lines changed

6 files changed

+517
-9
lines changed

conf/nginx.conf

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,20 @@ http {
2020
include mime.types;
2121
default_type application/octet-stream;
2222

23-
access_log off;
23+
log_format json_combined escape=json
24+
'{'
25+
'"time_local":"$time_local",'
26+
'"remote_addr":"$remote_addr",'
27+
'"cf_connecting_ip":"$http_cf_connecting_ip",'
28+
'"request_method":"$request_method",'
29+
'"request_uri":"$request_uri",'
30+
'"status":$status,'
31+
'"body_bytes_sent":$body_bytes_sent,'
32+
'"request_time":$request_time,'
33+
'"http_user_agent":"$http_user_agent"'
34+
'}';
35+
36+
access_log /dev/stdout json_combined;
2437

2538
# If there is an auth token, rate limit based on that,
2639
# else if there is a cloudflare ip header rate limit based on that,
@@ -31,11 +44,11 @@ http {
3144
default $http_authorization;
3245
}
3346

34-
# 1m stands for 1 megabyte so the zone can store ~8k users.
35-
limit_req_zone $limit_per_user zone=badge_user_limit:1m rate=1r/s;
36-
limit_req_zone $limit_per_user zone=assets_user_limit:1m rate=20r/s;
37-
limit_req_zone $limit_per_user zone=create_ann_user_limit:1m rate=4r/s;
38-
limit_req_zone $limit_per_user zone=user_limit:1m rate=4r/s;
47+
# 2m stands for 2 megabytes so the zone can store ~16k users.
48+
limit_req_zone $limit_per_user zone=badge_user_limit:2m rate=10r/s;
49+
limit_req_zone $limit_per_user zone=assets_user_limit:2m rate=20r/s;
50+
limit_req_zone $limit_per_user zone=create_ann_user_limit:2m rate=4r/s;
51+
limit_req_zone $limit_per_user zone=user_limit:2m rate=10r/s;
3952
limit_req_status 429;
4053

4154
# We set fail_timeout=0 so that the upstream isn't marked as down if a single
@@ -96,7 +109,7 @@ http {
96109
# load from any single user, and take advantage of latency
97110
# not being critical.
98111
location /api/badge {
99-
limit_req zone=badge_user_limit burst=15;
112+
limit_req zone=badge_user_limit burst=100 nodelay;
100113
error_page 429 @api_error_429;
101114

102115
proxy_pass http://web;
@@ -120,15 +133,15 @@ http {
120133
}
121134

122135
location /api {
123-
limit_req zone=user_limit burst=44 nodelay;
136+
limit_req zone=user_limit burst=200 nodelay;
124137
error_page 429 @api_error_429;
125138

126139
proxy_pass http://web;
127140
}
128141

129142
# An overall rate limit was chosen to allow reasonable usage while
130143
# preventing a single user from causing service disruption.
131-
limit_req zone=user_limit burst=44 nodelay;
144+
limit_req zone=user_limit burst=200 nodelay;
132145
}
133146
}
134147

0 commit comments

Comments
 (0)