Back to Technical Mode
Model Denial of Service
Because generating each token costs real compute and money, and because context windows can be enormous, an attacker who controls the size or structure of a prompt can drive a single request's cost and latency up by orders of magnitude, exhausting a shared rate/cost budget or degrading service for every other user.
Cost and latency scale with both input tokens and requested output tokens — an attacker controls both if the app doesn't cap them
Recursive or self-referential prompting ('keep expanding on your previous answer indefinitely') can turn one user request into an unbounded generation loop if there's no hard output cap
A shared rate limit or budget pool means one abusive user's oversized requests directly degrade every other user's experience and cost — this is a multi-tenant noisy-neighbor problem, not just a single-account issue
Model-side timeouts and max_tokens caps are necessary but not sufficient — the request-acceptance layer (before the model call even starts) needs its own input-size limits
Want this flow explained in detail as it plays?
POST/api/summarize
Headers
Host:app.flowground.dev
Content-Type:application/json
Body
Loading...
Quick-Insert Payloads
Defense in depth
- Enforce a hard input size limit (character/token count) at the API boundary, before the request is ever sent to the model — reject oversized input outright rather than truncating silently
- Always set an explicit, conservative max_tokens on the model call itself — never rely on the model's absolute maximum as the effective limit
- Apply per-user and per-IP rate limiting and cost budgets specifically for LLM-backed endpoints, separate from your general API rate limits, since a single LLM call's cost varies so much more than a typical CRUD request
Vulnerable vs. Fixed
app.post("/api/summarize", async (req, res) => {
const response = await llm.chat({
messages: [{ role: "user", content: `Summarize this: ${req.body.document}` }], // no size check on document
// no max_tokens set — defaults to the model's absolute maximum
});
res.json({ summary: response.text });
});