Skip to content

fix(proxy): reserve all standalone TPM counters in one Lua call - #46494

Closed
kerry-berri wants to merge 1 commit into
mainfrom
litellm_fix_tpm_reservation_pipeline_race
Closed

kerry-berri wants to merge 1 commit into
mainfrom
litellm_fix_tpm_reservation_pipeline_race

Conversation

@kerry-berri

Copy link
Copy Markdown
Contributor

TLDR

Problem this solves:

  • Concurrent requests on a team model_tpm_limit can all get 429, even when there's room for one
  • test_concurrent_team_model_tpm_requests_reserve_tokens_before_reaching_the_provider flaked on main in 6 of the last 22 CircleCI runs, always with (429, 429, 429)

How it solves it:

User Flow

Before: a team with a per-model TPM limit sees every concurrent request rejected, even though the limit has room for one

  1. The admin sets team metadata {"model_tpm_limit": {"gpt-4o-mini": 100}} and gives a key to that team
  2. The app sends 3 concurrent POST https://litellm-domain/v1/chat/completions with "max_tokens": 60
  3. Sometimes all 3 come back 429 Rate limit exceeded for model_per_key ... Remaining: 28 and none reach the provider

After: one request is served and the other two are rate limited

  1. The admin sets team metadata {"model_tpm_limit": {"gpt-4o-mini": 100}} and gives a key to that team
  2. The app sends 3 concurrent POST https://litellm-domain/v1/chat/completions with "max_tokens": 60
  3. One comes back 200 with provider usage and the other two get 429 Limit type: tokens. Current limit: 100

Affected release

Regression from #43407 (request-scoped Redis pipeline, merged 2026-09-29)

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have added meaningful tests
  • The handful of test files covering my change pass locally, e.g. uv run pytest tests/unit/<your_test_file>.py -v. Leave the suites (make test-unit-*, make test-unit) to CI: it finishes in ~15 minutes where a laptop takes an hour or more
  • My PR passes all required CI/CD checks (e.g., lint, schema.d.ts sync check, etc.)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • Every automated review on my PR's latest commit has finished, and I have addressed or replied to each of its findings before requesting a maintainer review

Delays in PR merge?

If you're seeing a delay in your PR being merged, ping the LiteLLM Team on Slack (#pr-review).

Screenshots / Proof of Fix

This is a race inside the rate limiter, so the proof is the existing integration test looped against one live proxy with real Postgres and Redis and a scripted upstream. Each iteration fires the test's 3 concurrent requests

Leg Code Runs Failed
A main (457b5d26c7) 50 serial 1, with (429, 429, 429) and Remaining: 28 on both model_per_key and model_per_team
B main with the request pipeline forced off 50 serial 0
C this branch 50 serial 0
C this branch 100, 2 loops in parallel 0

A debug log on leg A showed all 150 requests had a request batch open and 2 descriptor groups (model_per_key, model_per_team), so every reservation was 2 separate Lua calls in one pipeline

Caveats

On Redis Cluster, a request with more than one rate-limited counter now pays one round trip per counter for its reservation, which is what it paid before #43407. Those counters live on different slots, so one atomic call isn't possible there

_settle_pipelined_descriptor_groups now only ever gets one group, so its multi-group refund handling is unreachable. I left it in place to keep this diff small

Link to Devin session: https://app.devin.ai/sessions/b692f38aa3154bac8d195178279a7b1c
Open in Devin Desktop: https://app.devin.ai/desktop/session/b692f38aa3154bac8d195178279a7b1c?variant=devin
Requested by: @kerrylu-berri

@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codspeed

codspeed Bot commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

⚠️ 1 benchmark spent significant time in system calls

System calls cannot be consistently instrumented, so they are not included in the measure, which understates the real cost. Please switch to the Walltime instrument to accurately measure system calls.

Measurement and system calls

✅ 31 untouched benchmarks


Comparing litellm_fix_tpm_reservation_pipeline_race (4def448) with main (6e0f0f7)

Open in CodSpeed

@codecov

codecov Bot commented Oct 14, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.00000% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
litellm/proxy/hooks/parallel_request_limiter_v3.py 90.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

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