← Back to all articles

Protecting Expensive API Endpoints with Per-Tenant Controls

How tenant identity, endpoint context, behavioral signals, and proportional enforcement can protect shared API capacity more precisely than a single service-wide request counter.

Protecting Expensive API Endpoints with Per-Tenant Controls

How tenant identity, endpoint context, behavioral signals, and proportional enforcement can protect shared API capacity more precisely than a single service-wide request counter.

Galileo Galilei, the Italian astronomer, physicist, and mathematician whose work helped lay the foundations of modern experimental science, asked a deceptively simple question: do heavier objects fall faster than lighter ones? Everyday experience seems to say yes. Drop a hammer and a feather, and the hammer reaches the ground first. But the difference comes from air resistance, not mass itself. In the absence of air resistance, objects released from the same height accelerate toward the ground at the same rate.

Centuries later, Apollo 15 astronaut David Scott turned that idea into one of the most memorable demonstrations in physics. On August 2, 1971, he released a hammer and a feather at the same time on the Moon. With essentially no atmosphere to slow the feather, both reached the surface together. NASA’s account of the demonstration records the experiment as a tribute to Galileo.

Now the Proxyble team recently validated another observation around a different kind of “weight”: API cost. We compared requests that look identical to a request counter but place very different demands on the system behind it.

A cached metadata lookup and an AI inference request each count as one request. So does generating a large report, running a complex search, or exporting a large dataset. Yet the work behind those requests can differ dramatically in compute, database activity, execution time, bandwidth, and downstream service usage.

Galileo’s experiment showed that apparent differences in falling behavior can disappear once the surrounding conditions are understood. Our API experiment shows the opposite kind of trap: identical request counts can conceal very different resource demands.

The limits of request counting are explored in Why Static Rate Limits Fail for Modern APIs and What Comes After Them.

For a shared API, the practical problem is therefore not simply how many requests arrive. It is which tenant is making them, which endpoints they are calling, and how much resource pressure that behavior creates; especially when one tenant’s workload can consume capacity needed by everyone else.

Equal Request Counts Do Not Mean Equal Resource Pressure

An expensive endpoint is an endpoint whose requests can create substantially more resource pressure than ordinary API operations. The expense may come from application work, database access, external services, response volume, long-running execution, or some combination of these factors.

Consider two endpoints. The first returns cached metadata and requires little more than a cache lookup and a small response. The second generates a report by scanning a large dataset, joining several tables, rendering a document, and storing the result. One hundred requests to either endpoint produce the same request count. Their effect on the backend can be radically different.

The same distinction appears across many workloads:

  • AI inference and agent-execution endpoints may consume long-running compute or trigger multiple downstream operations.
  • Search endpoints may execute complex database queries.
  • Report-generation endpoints may scan, aggregate, transform, and render large datasets.
  • Export endpoints may read and serialize substantial amounts of data.
  • Image, video, and document-processing endpoints can require significant CPU, memory, or execution time.
  • Analytics APIs may scan large ranges or high-cardinality datasets.
  • Large-download endpoints may consume significant bandwidth and connection capacity.
  • Some endpoints invoke paid or capacity-constrained third-party services.

A global rate-limit such as 100 requests per second cannot describe these differences by itself. A client sending 50 inexpensive requests per second may impose little operational load, while another sending five expensive requests per second may create more resource pressure.

Two authenticated tenants sending equal numbers of requests to the same API. Tenant A uses inexpensive cached or read endpoints, while Tenant B invokes expensive operations that create greater backend resource pressure.

This problem exists even when the caller is fully authenticated and authorized. Authentication establishes who the caller is. Authorization establishes which operations that caller may perform. Neither, by itself, determines whether the caller’s behavior is creating acceptable pressure over time.

That pressure also does not establish malicious intent. It may result from deliberate abuse, but it may also come from compromised credentials, an incorrectly configured partner integration, a retrying batch job, runaway automation, an AI agent making repeated tool calls, or a legitimate customer using the API more aggressively than expected.

The distinction matters operationally. Expensive behavior describes effect. Malicious behavior describes intent or threat. A control system should not collapse the two.

Multi-tenant APIs add another complication. A tenant may represent a customer, organization, partner, account, service, API consumer, or another logical boundary meaningful to the surrounding system. Tenants using the same API can create very different resource profiles even when their total request counts are similar.

Aggregate service-wide measurements can obscure that difference. The service may remain below its overall request-rate limit while one tenant accounts for most export bandwidth, long-running requests, database-heavy searches, or inference activity. Conversely, a short increase in total traffic may be harmless if it consists mostly of inexpensive operations.

Request rate remains useful. It simply becomes one dimension of a larger problem.

Measure Behavior and Pressure, Not Just Volume

Protecting an expensive endpoint becomes more precise when request count is combined with signals that describe what the tenant is calling, how long operations remain active, how much data moves, how errors evolve, and whether the behavior persists.

The most basic additional signal is the endpoint or path itself. Ten requests to /metadata are not equivalent to ten requests to /reports/generate. Endpoint context gives meaning to other measurements.

Several observable dimensions are particularly useful:

Signal What it can contribute
Endpoint or path Identifies which operation is being exercised
Request rate Shows how frequently calls are being made
Concurrency Shows how many requests or operations remain active simultaneously
Connection behavior Reveals connection creation, reconnect patterns, or long-lived occupancy
Latency Shows how long requests remain active before completion
Response bytes Measures individual and accumulated data transfer
Errors and timeouts Shows repeated unsuccessful or incomplete operations
Retry behavior Shows whether clients repeatedly reissue work after failures or back-pressure
Endpoint spread Shows how broadly a consumer moves across related operations
Persistence over time Distinguishes brief bursts from sustained behavior

Different expensive endpoints expose different useful signals. And no single signal is universally decisive.

A traffic-control layer can directly observe facts such as requested paths, request frequency, response latency, status codes, bytes transferred, connection behavior, active work, and retry patterns. These signals can support a conclusion that pressure is increasing, but they should not be presented as exact measurements of CPU usage, database cost, cloud billing, inference cost, or third-party spend unless those measurements are actually available to the system.

Requests entering a behavioral measurement layer and accumulating context across time, with endpoint, request rate, concurrency, latency, response bytes, errors, retries, and connection behavior feeding a per-tenant behavioral picture.

The value often comes from combining several modest signals.

A moderate request rate may look harmless. Moderate latency may also look harmless. But sustained calls to a known expensive endpoint, rising concurrency, growing response volume, and repeated retries together can describe a workload that deserves attention even though no individual measurement crosses an obvious threshold.

This is why behavior is better evaluated across a campaign of requests than by treating each request independently. One 12-second response establishes little by itself. Neither does one timeout or one large download. A tenant repeatedly initiating long-running requests, maintaining elevated concurrency, producing large responses, and retrying failed operations over several minutes presents a different operational picture.

Proxyble analyzes API traffic and behavioral patterns in real time and maintains context across multiple requests. That context supports measurement and policy decisions.

The Tenant as a Control Boundary

Once the system can measure behavior across multiple requests, the next question is where to assign that behavior.

For a shared API, the tenant is often the most useful boundary because it represents the logical consumer responsible for the workload rather than only the network location from which traffic arrives.

Different control scopes answer different questions:

Control scope What it constrains Important limitation
Global Total activity across the service Cannot isolate one tenant from another
Source/IP Activity from a network source One tenant may use many IPs, or several tenants may share infrastructure
Endpoint Activity against a specific operation Does not identify which tenant creates the pressure
Tenant Activity associated with one logical consumer May still treat cheap and expensive endpoints equally
Tenant + endpoint One tenant’s behavior against a specific operation Requires trustworthy tenant attribution and endpoint context

These scopes are complementary. A service may use a global safeguard against total overload, network-level controls for hostile sources, endpoint-specific restrictions around costly operations, and tenant-specific policies for isolating resource use among consumers.

Consider three tenants sharing one API.

Tenant A performs frequent inexpensive reads. Tenant B makes fewer total requests but repeatedly calls /reports/export. Tenant C occasionally runs exports but otherwise produces moderate traffic.

A global request-rate threshold may not identify Tenant B as the source of the pressure. Tightening that threshold could reduce capacity available to A and C even though their behavior is not contributing materially to the problem.

An IP-based boundary may also be insufficient. Tenant B may send requests from several application servers, cloud instances, or regions. Conversely, several logical consumers may appear behind shared infrastructure. IP addresses remain useful network signals, but they should not be treated as equivalent to tenant identity.

A shared API serving three authenticated tenants with separate behavioral context and policy boundaries. Tenant B reaches an expensive-endpoint control without reducing the allowance available to Tenants A or C.

Tenant-aware controls depend on trustworthy identity context. Depending on the surrounding architecture, tenant identity may come from an authenticated client identity or trusted metadata propagated by infrastructure that has already established identity. The exact mechanism depends on the system.

The important requirement is that tenant attribution align with an established trust boundary. A runtime control should not infer tenant identity from an arbitrary client-supplied value.

This also clarifies the relationship between identity systems and behavioral governance. Authentication answers who the caller is. Authorization answers what the caller may do. Per-tenant runtime policy asks how that authorized consumer is actually using the API over time.

For the broader distinction between permitted access and behavior after access, see Behavior After Access: Adding Runtime Behavioral Security to the API Stack.

That distinction makes policies more expressive. One tenant may legitimately receive a larger allowance than another. An expensive endpoint may have a tenant-specific rate or concurrency limit. A large-download endpoint may be constrained more tightly for one class of tenant than for another. Responses may also change as observed behavior changes.

Per-tenant control is not synonymous with billing or quota management. A commercial quota may define how much of a service a customer purchased over a billing period. A runtime control may instead exist to protect backend capacity, contain abnormal behavior, or prevent one consumer from degrading service for others.

The tenant is therefore useful not because every system must enforce a customer quota, but because resource pressure often needs to be attributed to the consumer causing it.

Combine Tenant, Endpoint, and Behavioral Context in Policy

Once tenant attribution and behavioral measurement are available, a runtime policy can combine them rather than reducing every decision to one counter.

Conceptually, policy may consider:

tenant + endpoint + request rate + concurrency + observed pressure + recent behavior

The combination depends on the endpoint.

A large export may be governed primarily by endpoint rate, accumulated bytes, and concurrent operations. An inference endpoint may require more attention to request frequency, operation duration, and concurrency. A failing integration may be better identified through errors and retries.

Static controls still have an important role. A configured rule such as “this tenant may call /api/export no more than N times during a defined interval” is predictable and easy to reason about. Global limits, tenant-specific limits, endpoint-specific limits, and tenant-plus-endpoint limits can remain useful guardrails.

Behavior-informed policy adds context when a fixed threshold is not enough.

Scenario Observed behavior Useful policy scope Proportional response
Repeated exports Sustained export calls, large responses, increasing concurrent work Tenant + endpoint Reduce endpoint rate, concurrency, or bandwidth
Machine-speed AI activity Rapid inference or MCP tool calls with sustained concurrency and little idle time Tenant + endpoint + recent behavior Slow request rate or cap concurrent operations
Retry loop Errors followed by rapid repeated requests or connection creation Tenant + endpoint + retry history Slow requests, reduce connection rate, or temporarily busy-deflect
Short clean burst Brief rate increase with normal completion and no persistent error pattern Tenant + endpoint + recent history Allow or apply temporary pressure relief

Consider a tenant repeatedly invoking /api/export. Its overall request rate may be small relative to the service, so a global threshold may never trigger. Yet the tenant could accumulate substantial response bytes and keep several expensive operations active simultaneously.

The relevant policy scope is therefore the tenant and export endpoint together.

A static endpoint-rate rule can establish a hard guardrail. If pressure develops before that ceiling is reached, a behavior-informed policy may reduce the endpoint rate, cap active work, or constrain bandwidth where transfer volume is the dominant concern.

Now consider an AI agent calling an inference endpoint or MCP tool continuously at machine speed. No individual request needs to look malformed or unauthorized. The pattern emerges from frequency, persistence, concurrency, and the characteristics of the endpoint.

A static tenant limit may define the maximum permitted rate. Behavioral conditions can add sensitivity to sustained pressure below that ceiling. A proportional response might slow the effective rate or reduce concurrent work without immediately denying the tenant all access.

Retry loops require a different policy shape. Suppose a partner integration receives 5xx responses from an expensive operation and retries immediately. The original failure may come from the backend rather than the consumer, yet rapid retries can amplify the problem.

Recent error history and retry behavior matter more here than raw volume alone. A policy can reduce request frequency, limit connection creation, or return a temporary busy response to interrupt the amplification.

A short legitimate burst illustrates the opposite case. A tenant may suddenly increase expensive activity because a scheduled job started, queued work was released, or users returned after an interruption. If operations complete normally and the burst quickly subsides, the policy may allow the activity or apply only temporary relief.

Policy decision flow from tenant identity and endpoint context through measured behavior and recent history to proportional actions such as allow, rate-limit, reduce concurrency, slow bandwidth, timeout, reject, or drop.

This separation is important. Detection identifies behavior or pressure that meets configured conditions. Enforcement applies the action defined by policy. Neither step requires treating every anomaly as hostile.

Use Graduated Enforcement to Protect Capacity

Expensive-endpoint protection is more useful when enforcement can reduce resource pressure without automatically converting every event into a binary allow-or-block decision.

A reasonable progression may begin with observation. The system records the behavior and accumulates evidence without modifying traffic. This is useful when a pattern is unusual but not yet severe enough to justify intervention.

If pressure increases, policy may apply an endpoint-specific rate control. A tenant repeatedly generating exports, for example, can have /api/export constrained while unrelated API activity continues normally.

When a client should explicitly reduce its request rate, HTTP 429 responses provide a standard back-pressure signal. For long-running workloads, reducing concurrency may be more effective than limiting raw requests per second. A tenant can continue using the endpoint while fewer expensive operations execute simultaneously.

When large responses dominate resource pressure, bandwidth limiting can reduce transfer impact without denying access entirely. Temporary busy responses can provide short-lived relief during service pressure. Shorter timeout exposure can reduce how long certain requests are allowed to occupy backend capacity.

Graduated enforcement ladder for a tenant repeatedly consuming an expensive endpoint, progressing from observation and normal access through rate control, resource reduction, temporary restriction, and finally reject or drop as behavioral risk and confidence increase.

Consider a legitimate tenant that suddenly generates a large number of expensive reports. The burst may come from a scheduled job or an unexpected increase in legitimate usage. If the behavior is brief and responds to back-pressure, temporary rate or concurrency reduction may be enough.

A long ban would continue affecting the tenant after the pressure had passed.

Now consider persistent behavior that repeatedly recreates high concurrency and continues retrying after rate limits or temporary busy responses. Earlier controls may no longer provide enough relief. Policy can move to stronger temporary restrictions.

That persistence still does not prove malicious intent. A client that continues after receiving 429 responses may have a defective retry strategy, multiple independent workers, or an outdated integration. Enforcement should respond to the resulting pressure and policy conditions rather than unsupported assumptions about motive.

Proxyble supports graduated runtime responses including endpoint-rate controls, 429-based slowdown, connection and concurrency limits, bandwidth limits, busy deflection, timeout control, temporary restrictions, and stronger reject or drop actions when policy justifies them.

More forceful actions such as REJECT or DROP are better reserved for sufficiently severe or high-confidence cases. They are not the default response merely because an operation is expensive.

Place Runtime Protection in the Existing API Architecture

These controls need an enforcement position from which they can affect live traffic before unnecessary expensive work accumulates.

One of the option for simple inline architecture is:

Client → Load Balancer / WAF → API Gateway → Proxyble → Application

Inline API architecture showing Client through the load balancer or WAF, API gateway, Proxyble, and Application, with trusted tenant identity and request context feeding runtime policy before expensive application operations.

The components have overlapping capabilities in some environments, but their primary responsibilities can still be separated conceptually.

Authentication and IAM establish who the caller is. Authorization determines which operations the caller may perform. API gateways may provide routing, quotas, rate limits, transformations, and other API-management functions. WAFs and related security infrastructure may inspect and filter threats. CDNs can absorb and cache traffic where appropriate. Observability and SIEM systems provide logs, metrics, traces, alerts, correlation, investigation, and in some architectures automated response. Service meshes and application controls may also enforce traffic, reliability, and security policies.

Proxyble operates as a reverse proxy with built-in real-time analytics and runtime enforcement. Its role in this architecture is to maintain behavioral context across requests and apply configured controls to live API traffic.

For deployment patterns that keep this analysis inside private infrastructure or a disconnected environment, see Behavioral API Security Without Sending Your Traffic Outside Your VPC.

Enforcement position matters because an action taken before an expensive backend operation begins can prevent some unnecessary work from being admitted at all.

If a policy limits a new export request, inference operation, or large download before the application starts processing it, the backend does not need to spend the associated resources on that request.

Not every useful signal exists before processing. Response latency, response status, and response size become known only as requests progress or complete. Those observations can update behavioral context and influence how subsequent requests from the same tenant are handled.

Per-tenant policy also requires the architecture to preserve trustworthy tenant context. If identity is established upstream, the information passed into the runtime enforcement layer must be sufficient to associate traffic with the correct tenant. The exact propagation mechanism depends on the existing trust architecture.

Proxyble can enforce these behavioral policies in the traffic path without requiring application logic to implement every control independently.

Other deployment models also available. A process running beside an application is not automatically part of the request path merely because it is deployed as a sidecar.

A Practical Adoption Model

Teams do not need a perfect cost model before they can begin protecting expensive endpoints.

A practical sequence starts with endpoints already known to create disproportionate operational impact and adds precision as production evidence accumulates.

1. Identify disproportionately expensive endpoints

Start with operations that engineers already recognize as heavy: exports, inference, report generation, complex searches, analytics, large downloads, document processing, or calls that depend on costly downstream services.

The first version of the inventory does not need to be exhaustive.

2. Identify observable pressure signals

Determine which measurable characteristics tend to accompany pressure for each endpoint.

For an export API, accumulated bytes and concurrency may matter more than requests per second. For an inference endpoint, sustained activity and long-running concurrent work may be more useful. For a failing partner integration, retries and errors may be the clearest indicators.

3. Establish the consumer boundary

Associate activity with a tenant or another meaningful consumer identity using trustworthy context already present in the architecture.

This is what allows the system to distinguish “the service is under pressure” from “Tenant B is producing most of the pressure on /api/export.”

4. Establish baseline behavior

Useful baselines may include normal request rates, concurrent work, operation duration, response volume, retry patterns, error behavior, and ordinary bursts.

The purpose is not to define one universal normal profile. It is to give policy designers evidence about how the API is actually used.

5. Define static guardrails

Some controls should remain explicit and simple.

A maximum tenant-specific endpoint rate, concurrency ceiling, or connection limit can provide a clear safety boundary even when there is no behavioral anomaly.

Static rules also make policy easier to reason about during incidents.

6. Add behavioral conditions where static limits are insufficient

A tenant may remain below every simple request threshold while still creating sustained pressure.

This is where recent behavior becomes useful. Endpoint context, concurrency, retries, bytes, latency, errors, connection behavior, and persistence can be combined where they are relevant.

7. Choose proportional enforcement

Select actions based on the operational objective.

If the goal is to reduce new expensive work, an endpoint-rate limit may be appropriate. If simultaneous execution is the problem, concurrency control may be better. If response transfer dominates, bandwidth shaping may help. If the backend is already under pressure, temporary busy responses or shorter timeout exposure may reduce amplification.

Stronger rejection should require stronger justification.

8. Preserve evidence

Record enough context to understand why enforcement happened.

Operators need to know which tenant was affected, which endpoint was involved, what behavior was observed, and what policy action followed. Proxyble’s behavioral analysis and evidence context support this review.

9. Tune from production outcomes

Policy design is iterative.

Controls that are too permissive may fail to protect capacity. Controls that are too aggressive may interfere with legitimate tenants. Production evidence provides the basis for adjusting thresholds, conditions, and responses.

A team may initially know only that /reports/export produces large responses and stays active for a long time. That can still justify per-tenant endpoint-rate and concurrency controls. Later, operational evidence may show that retries, accumulated bytes, or particular traffic patterns provide more useful indicators.

Per-tenant controls also preserve isolation. When one consumer creates pressure on an expensive operation, policy can focus on that tenant and endpoint instead of unnecessarily reducing service for unrelated consumers.

A Final Word from Galileo

We have to admit, that Galileo was right: once the relevant conditions are understood, apparent weight does not tell the whole story. API must be governed according to the work client create, not the superficial count of requests alone.

More than four centuries later, the laws uncovered by a Renaissance-era genius are still helping us shape the new laws of API security.