1. Soft limits versus hard cost limits: the difference between measuring and intervening
In many software organizations, cost control is confused with cost monitoring. With monitoring, an alert is sent when a preset budget is exceeded, for example through an email to the DevOps team or a webhook to a Slack channel. This is called a soft limit . The fundamental problem with a soft limit is that the signal is reactive and depends on human intervention or a delayed processing pipeline at the API provider. Large LLM providers often process consumption metrics in batches. It can take up to six hours before the dashboards and budget alerts of a provider such as OpenAI or Anthropic are updated. An application that sends a thousand requests per minute because of a faulty loop has already blown far past the monthly budget by the time the email arrives. For setting up dashboards and alerts, we recommend consulting the guide on monitoring API costs .
A hard cost limit (hard cap), by contrast, works inline and preventively. Enforcing a hard limit requires that every outgoing API call is validated synchronously against a current budget register before the request is forwarded to the provider. If the budget is spent, the gateway refuses the call immediately at the network level with an HTTP 429 (Too Many Requests) or HTTP 402 (Payment Required) status code. At that moment no outgoing network traffic to the LLM provider takes place, guaranteed.
2. Architecture of an inline budget cap engine
To enforce a hard budget cap without increasing the latency of every API call unacceptably, the budget engine has to sit right in front of the outgoing provider calls, usually as a middleware component within a self-hosted LLM gateway.
The technical process of an inline cost validation runs through the following steps:
- Request interception: The gateway receives the incoming request from the client and identifies the tenant, the API key and the requested model.
- Reservation phase (pre-check): The budget engine consults an in-memory datastore (such as Redis) to check whether the accumulated historical costs plus the estimated costs of the incoming call stay below the limit.
- Boundary check: If the reservation exceeds the threshold, the gateway aborts the request immediately.
- Execution & update (post-call): If the request falls within the boundaries, the call is sent to the provider. Once the response (including the exact number of prompt and completion tokens processed) has been received, the gateway calculates the exact price based on the price table for that specific model and adds it to the cumulative consumption register.
3. Quota allocation at tenant, user and key level
A global budget cap at organization level keeps you from going bankrupt, but is not enough for multi-tenant applications or SaaS platforms. If one single end user burns through the company's entire monthly budget, you have a denial of service at organization level. Hard limits therefore have to be enforced in a hierarchical structure.
Find out how to distribute consumption at organization level in the article on attributing costs per end user. In practice we use three levels of quota enforcement:
- Organization strength (global hard cap): An absolute upper limit per calendar month (€2,000, for example) that protects the total API account.
- Tenant / customer level (tenant quota): An allocated budget per subscribed customer or department (for example €50.00 per month for a Standard tier, €500.00 for Enterprise).
- API key / session level (key / burst limit): A short-term quota to absorb peaks and slow down automated scripts (for example a maximum of €2 per hour per API key).
| Level | Typical limit | Reset frequency | Action when exceeded |
|---|---|---|---|
| Global hard cap | € 5.000,00 | Monthly | Kill switch: block all outgoing provider calls |
| Tenant quota | € 100,00 | Monthly / rolling | Return HTTP 429 with Retry-After header |
| Key / burst limit | € 5,00 | Hourly | Switch to a cheaper fallback model |
4. The kill switch: emergency stop without application downtime
A kill switch is a manual or automated emergency button that immediately halts all traffic to one specific LLM provider, model or tenant. Where a budget cap works on the basis of cumulative consumption over time, a kill switch steps in on acute anomalies, such as an unexpected cyberattack, a faulty software deployment or an extreme rise in the number of errors.
System failure mode: the automated kill switch in action
The production pattern below describes how an automated kill switch is built to prevent API cost escalation during system failures:
- Failure mode: A faulty loop in a client application (for example an infinite retry loop after a failed parse) fires 500 requests per second at the LLM gateway, driving the expected monthly costs up by thousands of euros within ten minutes.
- Detection: The gateway performs a sliding window measurement. If the cost rate (the burn rate) is higher than, say, €10.00 per minute for two consecutive minutes, the gateway automatically triggers the circuit breaker mechanism.
- Mitigation: The status of the tenant or API key in question is immediately switched in the central Redis datastore to
STATUS_BLOCKED. All incoming requests from this source are refused at the gate without processing. - Cost of mitigation: Within the affected component there is a temporary loss of functionality (latency for refused requests drops to < 2 ms, but the client receives errors). No cost escalation toward the provider takes place, however: 0 euros.
5. Pitfalls, race conditions and token estimation with streaming responses
Enforcing hard limits on LLM APIs brings unique technical challenges that do not exist with traditional REST APIs with fixed costs per request. The biggest problem is that the exact cost of a call is only known after the response has been fully generated by the model.
The technical background of rate limiting at network level can be found in the guide on the token bucket algorithm in a gateway. When we apply this same mechanism to financial costs instead of request counts, we run into two specific pitfalls:
Race conditions with concurrent requests
If a user has a balance of €0.05 and simultaneously submits ten API requests that each cost an estimated €0.02, all ten requests will pass the pre-check if the check is not performed atomically. After processing, the total cost comes to €0.20, exceeding the budget by 300%.
Solution: Use atomic reservations in Redis via Lua scripts. When a request starts, the gateway does not only check current consumption; it immediately subtracts a provisional reservation (based for example on the max_tokens parameter) from the balance. Only after the call has completed is the actual consumption settled and the excess reservation released.
The leak with streaming responses (Server-Sent Events)
With streaming responses (SSE), the LLM provider sends the generated text back token by token. If a user hits their budget cap halfway through the stream, the request keeps running in the background at the provider as long as the HTTP connection stays open. The provider keeps generating and billing tokens, even if the user has closed the browser.
Solution: The gateway has to keep an active token counter while streaming the SSE chunks. As soon as the reserved token budget is exceeded during streaming, the gateway must not only cut the connection to the client, but explicitly send an HTTP DELETE or abort signal (such as a TCP RST or canceling the request through the SDK) to the outgoing connection with the LLM provider, in order to stop the generation process on the provider's side immediately.
6. Pseudocode: inline budget enforcer middleware
The provider-independent pseudocode below demonstrates how an inline budget enforcer with atomic reservation, error handling and timeout management is worked into a gateway pipeline.
async function handleIncomingLlmRequest(request, context) {
const tenantId = request.headers['x-tenant-id'];
const model = request.body.model;
const promptText = request.body.prompt;
// 1. Bereken geschatte kosten op basis van inputtokens + max_tokens
const estimatedInputTokens = estimateTokenCount(promptText);
const maxTokens = request.body.max_tokens || 2048;
const estimatedCost = calculateMaxCost(model, estimatedInputTokens, maxTokens);
// 2. Probeer atomaire reservering uit te voeren in Redis (timeout 50ms)
const reservationSuccess = await redisLuaExecute('reserve_budget', [
tenantId,
estimatedCost
], { timeoutMs: 50 }).catch(err => {
// Fallback bij Redis storing: kies voor veiligheid of geef door op basis van beleid
logError('Redis reservation failed, failing safe', err);
return false;
});
if (!reservationSuccess) {
return new Response(JSON.stringify({
error: "BudgetCapExceeded",
message: "Harde kostenlimiet bereikt voor deze periode. Verzoek geweigerd."
}), { status: 429, headers: { 'Content-Type': 'application/json' } });
}
// 3. Voer het API-verzoek uit naar de provider met een strikte timeout
let providerResponse;
try {
providerResponse = await fetchLlmProvider(request, { timeoutMs: 15000 });
} catch (error) {
// Foutpad: annuleer de reservering als de provider-call mislukt
await redisLuaExecute('release_reservation', [tenantId, estimatedCost]);
return new Response(JSON.stringify({ error: "ProviderError", message: error.message }), { status: 502 });
}
// 4. Verwerk de werkelijke kosten en pas de reservering aan
const actualPromptTokens = providerResponse.usage.prompt_tokens;
const actualCompletionTokens = providerResponse.usage.completion_tokens;
const actualCost = calculateExactCost(model, actualPromptTokens, actualCompletionTokens);
// Synchroniseer het werkelijke verbruik (trek reservering recht met werkelijkheid)
await redisLuaExecute('settle_budget', [tenantId, estimatedCost, actualCost]);
return providerResponse;
}
7. Graceful degradation: what to do when the budget cap is reached?
Simply returning an error when a budget has been reached is sometimes undesirable from a business perspective. A well-designed API architecture applies graceful degradation . Depending on the configuration, the gateway can use the following strategies when the limit is approaching or has been reached:
- Model downgrading: Switching from an expensive flagship model (for example GPT-4o or Claude 3.5 Sonnet) to a model an order of magnitude cheaper (such as GPT-4o-mini or Claude 3 Haiku). This keeps the functionality intact at a fraction of the cost. To level out costs across different AI providers, read more about normalizing token consumption across providers.
- Cache-only mode: Refused requests are not forwarded to the provider; instead only a semantic or exact response cache is searched for hits. If there is no cache hit, a controlled message follows.
- Prompt truncation & output limiting: The number of allowed `max_tokens` for the completion is hard-coded down to 150 tokens, for example, to prevent long answers.
8. Organizational embedding and AI governance
Enforcing hard cost limits is not only a technical matter; it sits at the intersection of software architecture, finance and IT governance. A hard kill switch that shuts down a critical business process because a notional budget is exceeded by one euro can be more damaging to the organization than the API bill itself.
It is essential that budget limits are tuned dynamically to the business value of the specific application. Anyone who wants to anchor financial frameworks in the organization's governance should read the guide on drafting an AI policy for your organization. Clear agreements about who is authorized to override a kill switch or temporarily raise a budget have to be established in advance in the platform team's operating procedures.
9. Conclusion and operational checklist
Introducing LLM APIs into a production environment without hard inline cost limits is a considerable financial risk. Soft limits and reactive alerts do not offer enough protection against loops, spam attacks or unforeseen peaks in processing volume. By including a distributed budget engine in your LLM gateway, applying atomic reservations and setting up automated kill switches, you keep full control over your API spending.
Checklist for your cost infrastructure:
- [ ] Is there an inline check in place that blocks requests before they reach the LLM provider?
- [ ] Do you use atomic reservations (through Redis Lua, for example) to prevent race conditions with concurrent requests?
- [ ] Are streaming SSE connections actively cut off when token limits are exceeded?
- [ ] Is there a hierarchy of budgets per organization, tenant and API key?
- [ ] Is an automated kill switch active that responds to an abnormal rise in costs per minute?


