Skip to content

Add rate limiting to protect against DDoS#90

Merged
chapati23 merged 13 commits intomainfrom
feat/rate-limiting
Feb 9, 2026
Merged

Add rate limiting to protect against DDoS#90
chapati23 merged 13 commits intomainfrom
feat/rate-limiting

Conversation

@chapati23
Copy link
Contributor

Description

Implements HTTP rate limiting to mitigate potential DoS attacks.

  • Add global rate limiting via @nestjs/throttler (10 req/s, 50 req/10s, 100 req/min)
  • Cache health endpoint responses (30s TTL) to prevent payload amplification
  • Configure Express to trust proxy headers for correct client IP detection on Cloud Run
  • Replace Jest with Vitest for faster test execution

Context

The health endpoint is somewhat vulnerable to DoS as each request triggers 5+ external API calls (Blockstream, Blockchain.info, RPC nodes, etc.) without caching.

Key Changes

File Change
src/app.module.ts ThrottlerModule with 3-tier rate limiting
src/main.ts trust proxy for Cloud Run load balancer
src/api/health/health.controller.ts 30s response caching
vitest.config.ts New test runner setup

How to test

  1. Verify rate limiting works:

    # After deploying to preview, run this to trigger rate limit
    for i in {1..15}; do curl -s -o /dev/null -w "%{http_code} " https://<preview-url>/api/v1/health; done
    # Should see some 429 responses after ~10 requests
  2. Verify health caching:

    # First request populates cache, second should be instant
    time curl https://<preview-url>/api/v1/health
    time curl https://<preview-url>/api/v1/health  # Should be faster
  3. Run tests locally:

    pnpm test
  4. Code review focus:

    • Rate limit thresholds in src/app.module.ts - are 10/s, 50/10s, 100/min appropriate?
    • Health cache TTL (30s) in src/api/health/health.controller.ts

Copy link
Contributor

@Andrew718PLTS Andrew718PLTS left a comment

Choose a reason for hiding this comment

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

Code LGTM (one tiniest comment), unit tests passed successfully, but unfortunately, I can't test new changes because of preview deployment failure - pls check and fix that.

Great that you've added the unit tests setup, I like it.

Additionally, it'd be nice to run the unit tests on CI on push - it's so fast and doesn't require massive changes - actually a couple of lines (check the example from FE monorepo).

@Andrew718PLTS
Copy link
Contributor

Andrew718PLTS commented Feb 6, 2026

One more thing you can do just because you're here now (this is optional, I'll do this in some other PRs otherwise):
The current coverage of the health controller is 63% - sounds like a good task for AI to add new tests.

image

@github-actions github-actions bot temporarily deployed to preview-90 February 8, 2026 11:33 Destroyed
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

🚀 Preview Deployment

Your preview deployment is ready!

🔗 Preview URL: https://analytics-api-preview-feat-rate-limiting-a4neydykmq-uc.a.run.app/docs

📝 Details:

  • Service: analytics-api-preview-feat-rate-limiting
  • Commit: 1d49990
  • Branch: feat/rate-limiting
  • Updated: 2/9/2026, 1:24:09 PM UTC

This preview will be automatically updated with each new commit to this PR and will be deleted when the PR is merged or closed.

@github-actions github-actions bot temporarily deployed to preview-90 February 8, 2026 12:50 Destroyed
@github-actions github-actions bot temporarily deployed to preview-90 February 8, 2026 13:04 Destroyed
@Andrew718PLTS Andrew718PLTS self-requested a review February 9, 2026 12:34
Copy link
Contributor

@Andrew718PLTS Andrew718PLTS left a comment

Choose a reason for hiding this comment

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

I ran performance tests to verify caching and DDoS protection using a GET /health request.
It simulates 5 users sequentially sending for 1m (Total requests sent: 231).
Here's the summary based on results:

Cache

It took 12s to populate the cache and start using it.

DDoS Protection

We started erroring out with the 429 status approximately in the middle of execution.

Conclusions

LGTM, just a few comments below:

  1. The only thing I'd highlight is that I wouldn't mention ThrottlerException in the error message. I don't wanna show any sign of throttling for potential attackers) But it still might be mentioned in the internal logs.
  2. Additionally, I ran tests with 50 users for 1m and saw that we also have ESOCKETTIMEDOUT error. There are only 7 out of ~1500, but we still might need to look it up and potentially fix it.
Image Image

@github-actions github-actions bot temporarily deployed to preview-90 February 9, 2026 13:24 Destroyed
@Andrew718PLTS Andrew718PLTS self-requested a review February 9, 2026 13:30
@chapati23 chapati23 merged commit 09f28ec into main Feb 9, 2026
3 checks passed
@chapati23 chapati23 deleted the feat/rate-limiting branch February 9, 2026 13:45
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.

2 participants