A request rate limit is only one of the controls OWASP API4:2023 asks for. An API also needs caps on payload size, records per page, execution time, memory, operations per request and third-party spend. Missing any of them can allow denial of service or a surprise bill.
What API4 is about
OWASP describes the risk plainly: serving requests uses bandwidth, CPU, memory and storage, and some third-party services charge per request. An API is vulnerable when limits on those things are missing or set poorly. The attacks are easy and often need only simple requests from one machine.
The damage is not always an outage. It can be money.
The checklist
Per request
- Maximum body size, and maximum string length and array size inside it.
- Maximum upload file size.
- Maximum operations per request, which matters for batched APIs.
- Server-side validation of any page size or count parameter, so nobody can ask for a million records.
- A timeout on execution.
Per client
- A request rate limit per key, user or address over a time window, with stricter limits on sensitive endpoints.
- Throttles on repeated sensitive actions per user, such as one time passcode checks and password recovery. See the post on throttling reset and passcode endpoints.
Per process
- Memory, CPU, restart and file descriptor limits on containers or serverless functions.
Per bill
- Spending limits with providers, or billing alerts where limits do not exist.
- Cost alerts on storage egress and any metered third-party API you call.
Three scenarios from OWASP
An attacker repeatedly triggers an SMS password reset, so the backend sends tens of thousands of paid messages within minutes. A GraphQL upload endpoint is checked for rate and size, but batching many uploads into one request exhausts memory. A file outgrows the cache size, so clients fetch it straight from cloud storage, and with no spending cap the monthly bill rises from about 13 dollars to about 8,000.
None of these is a clever exploit. Each is a missing number in a config file.
Where limits usually go missing
- Limits on the public route but not on the internal route that reaches the same code.
- A per-request limit that ignores batching.
- Caps on size but not on cost, for example a small request that triggers a heavy report.
- Background jobs triggered by the API that have no concurrency cap.
How to roll this out
Start with measurement. Log request sizes, durations and page sizes for a week. Set the limit at a comfortable multiple of normal and tighten later. Return clear errors, and test that the limits actually fire, because an untested limit tends to be silently inactive.
Quick check
If we have a gateway rate limit, are we covered?
No. It does not cap payload size, batch size, spend or heavy queries, and it may not apply to internal paths.
Where do I start if I have none of this?
Page size, body size and the rate limit on login and reset endpoints. Those give the most protection for the least effort.
Click through it at your own pace, or open it full screen.
Safeguard's free scan at gold.safeguard.sh/scan checks dependencies and SBOMs, and its asset discovery can help you find services that sit outside your gateway.
Sources
Last reviewed: 19 October 2026.