Skip to content

Nginx config changes [staging] - #496

Merged
duckduckgrayduck merged 4 commits into
stagingfrom
nginx_config_changes
Oct 28, 2026
Merged

duckduckgrayduck merged 4 commits into
stagingfrom
nginx_config_changes

Conversation

@duckduckgrayduck

@duckduckgrayduck duckduckgrayduck commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor
  • Returns a 429 instead of a 503 which nginx does by default for rate limited clients.

  • Rejects requests > 25MB in size site-wide. Github webhooks payloads are 25MB capped, Add-On events we shouldn't allow for much more than that either. Documents go to S3. Mailgun attachments are fetched by URL. This is set by NGINX_MAX_BODY_MB so we can bump it later if we need to.

  • Add CORS headers to the nginx 429 response and add Retry-After that the front-end and python-squarelet can key off of.

  • Bumps keepalive_timeout to 95s, to be >90s which is Heroku router's idle limit so we stop seeing H18. Issue

Follow-ups

  • python-squarelet: retry 429s for all methods and respect Retry-After, then bump the pin in python-documentcloud
  • Frontend: handle 429 responses and back off

Testing

  • nginx -t passes on the rendered config (Done)
  • Staging: rate-limited requests return 429 with Retry-After and CORS headers; normal responses don't get Retry-After
  • Staging: request bodies > 25MB return 413

@mitchelljkotler mitchelljkotler left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we only limiting addon_events to the max body size? We should probably have one site wide limit.

Also, as a note, when we change to using 429 status correctly we should also update the frontend (which will require adding CORS headers to the 429) and the python library to respond to them appropriately.

We can also set a retry-after header which should make the python client respect it automatically:

# only nginx's own 429s; DRF throttles set their own Retry-After
map "$upstream_status:$status" $retry_after {
    default "";
    ":429" 1;
}

server {
    ...
    add_header Retry-After $retry_after always;

…18s, add Retry-After and CORS headers to nginx-generated 429s so the frontend can read them and clients can back off
@duckduckgrayduck
duckduckgrayduck changed the base branch from master to staging October 26, 2026 22:22
@duckduckgrayduck duckduckgrayduck changed the title Nginx config changes [production] Nginx config changes [staging] Oct 26, 2026
@duckduckgrayduck

duckduckgrayduck commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Why are we only limiting addon_events to the max body size? We should probably have one site wide limit.

Also, as a note, when we change to using 429 status correctly we should also update the frontend (which will require adding CORS headers to the 429) and the python library to respond to them appropriately.

We can also set a retry-after header which should make the python client respect it automatically:

# only nginx's own 429s; DRF throttles set their own Retry-After
map "$upstream_status:$status" $retry_after {
    default "";
    ":429" 1;
}

server {
    ...
    add_header Retry-After $retry_after always;

I think this is ready for another look. I'll have to test the last two bulletpoints when it merges into staging.

@duckduckgrayduck
duckduckgrayduck merged commit 885b83e into staging Oct 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants