Skip to content

CMR-11195: As a developer, I want incoming CMR search requests classified and rate limited by compute cost so that heavy requests cannot cascade into backend failures - #2489

Merged
daniel-zamora merged 29 commits into
masterfrom
CMR-11195
Sep 2, 2026
Merged

CMR-11195: As a developer, I want incoming CMR search requests classified and rate limited by compute cost so that heavy requests cannot cascade into backend failures#2489
daniel-zamora merged 29 commits into
masterfrom
CMR-11195

Conversation

@daniel-zamora

@daniel-zamora daniel-zamora commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Overview

What is the objective?

Introduce a traffic-shaping proxy in front of CMR search that classifies requests into priority lanes (express/standard/heavy), applies distributed rate limiting via Redis semaphores, and caches responses to reduce backend load.

What are the changes?

New search-proxy FastAPI service with three traffic lanes, each with configurable concurrency permits and response cache TTLs
Redis-backed distributed semaphores for per-lane in-flight request counting across instances
Response cache keyed on method, path, query, auth token, Accept header, cmr-search-after cursor, and POST body hash
Request classifier routing traffic to lanes based on spatial complexity, facets, temporal params, and other signals
Feature toggles for bypass, caching, load shedding, and classification via ECS environment variables
AWS infrastructure: ECS task definition, ECR repository, ALB listener rules (priority 83 bypass rule to prevent routing loop, priority 84 proxy rule)
Health endpoint exposing Redis, backend, and per-lane utilization status

What areas of the application does this impact?

List impacted applications

All CMR search traffic (collections and granules endpoints) in environments where enable_search_proxy = true
Internal ALB routing rules
ElastiCache Redis (new usage for semaphores and cache)

Required Checklist

  • New and existing unit and int tests pass locally and remotely
  • clj-kondo has been run locally and all errors in changed files are corrected
  • I have commented my code, particularly in hard-to-understand areas
  • I have made changes to the documentation (if necessary)
  • My changes generate no new warnings

Additional Checklist

  • I have removed unnecessary/dead code and imports in files I have changed
  • I have cleaned up integration tests by doing one or more of the following:
    • migrated any are2 tests to are3 in files I have changed
    • de-duped, consolidated, removed dead int tests
    • transformed applicable int tests into unit tests
    • reduced number of system state resets by updating fixtures. Ex) (use-fixtures :each (ingest/reset-fixture {})) to be :once instead of :each

Comment thread search-proxy/src/proxy/app.py
Comment thread search-proxy/README.md Outdated
Comment thread search-proxy/README.md
Comment thread search-proxy/README.md Outdated

### `GET /health`

Informational health check. Always returns HTTP 200 — dependencies report their status but do not affect the top-level `ok?`. The result is cached for 5 seconds (unhealthy results are not cached so recovery is visible immediately).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It always returns 200? So what's the point of checking the health if it always returned 200?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So that the ELB health check doesn't bounce the tasks because redis is down. I can take another look and see if this is still needed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what was the conclusion to this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yea we decided that we shouldn't have the search-proxy task fail and restart if its connection to redis or elastic is bad, or they have what would otherwise be a bad status.

Comment thread search-proxy/README.md

class TestLoadShedding:
async def test_sheds_when_full(self, tight_lanes):
async with tight_lanes.acquire("heavy"):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think every test should have comment of "When... Then..." for easier reading. Although the naming of the python tests are clear enough in this case. So I would categorize this request as 'nice to have', if we can be consistent with tests having comments.

@daniel-zamora daniel-zamora Aug 31, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yea, I think that is reasonable. Can we move it to a separate ticket?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah that's fine

Comment thread search-proxy/test/test_config.py
Comment thread search-proxy/src/proxy/app.py Outdated
Comment thread search-proxy/src/proxy/lanes.py
@codecov-commenter

codecov-commenter commented Aug 31, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.96%. Comparing base (c5cd748) to head (e3d2ad3).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2489      +/-   ##
==========================================
- Coverage   57.96%   57.96%   -0.01%     
==========================================
  Files        1074     1074              
  Lines       74707    74707              
  Branches     2193     2189       -4     
==========================================
- Hits        43307    43303       -4     
- Misses      29354    29356       +2     
- Partials     2046     2048       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@daniel-zamora
daniel-zamora merged commit 3fdcbe2 into master Sep 2, 2026
6 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.

5 participants