Imagine your service runs a public submission endpoint. A contact form, a claims intake API, a feedback portal. For years it handled a few thousand submissions a month, mostly short, mostly human. Then, over a single quarter, the average submission triples in length, the vocabulary turns oddly legalistic, and your processing team quietly drowns. Nothing was breached. No bot swarm hammered your servers. Every single request came from a real, logged-in, paying or entitled user. They just all used AI to write.
That scenario is no longer hypothetical. A study accepted to the AAAI Conference on AI, Ethics, and Society documents 84 recent cases of exactly this pattern across 11 jurisdictions, and it is on Hacker News right now. The researchers call it agentic flooding: surges in the volume or complexity of requests that strain a service's capacity, enabled by AI agents lowering the cost of interacting with it.
The paper is about government services. But if you read it as a backend engineer, every mechanism it describes translates one-to-one to any public API with a submission surface. And most of the defenses it recommends are things you can build in Spring Boot this week. That is what this article is: the research, the numbers, and the code.
One disclosure before we start. I have not worked on a government service, and the cases below come from the researchers' dataset, not my own experience. The Spring Boot patterns, however, come from the kind of production hardening work any public-facing backend eventually needs. Treat the research as their contribution and the code as mine.
What the study actually found
The paper, by Chris Schmitz, Lewis Hammond, and Alan Chan, is worth reading directly. Here are the numbers that matter for engineers.
Flooding is already happening, widely. The team scanned 2,288 candidate government services across 12 countries, applied strict inclusion criteria requiring official or third-party attribution of the surge to AI, and kept 84 cases. In 58 of those 84 cases, 69 percent, government officials themselves asserted AI involvement. The most affected domains: justice and legal services (23 percent of cases), regulatory complaints (12 percent), and benefits and social protection (11 percent).
The mechanism is boringly simple. In 87 percent of cases, the flooding came from LLMs generating large amounts of sophisticated text, submitted by humans who navigated the rest of the process manually. Not autonomous browser agents. Not malicious botnets. Ordinary people, pasting model output into a form. The paper notes one case where submitted letters spanned over 4,000 pages. German social courts largely attributed a 55 percent year-on-year caseload rise in 2025 to AI-generated claims, and Australia has considered reintroducing Freedom of Information fees in response to a wave of AI-drafted requests.
Flooding comes in two flavors, and they need different defenses. The researchers distinguish quantitative flooding (more requests) from qualitative flooding (each request is heavier). They coded 60 percent of cases as quantitative, 90 percent as qualitative, and half exhibited both. This split is the single most useful engineering insight in the paper, because a rate limit stops the first kind and does almost nothing about the second. A user submitting one four-thousand-page document per hour is perfectly rate-limit-compliant.
Most services were protected by friction, not design. The highest-severity cases, tax valuation objections, social court lawsuits, civil claims, shared two properties: each successful submission is individually consequential, and the service's resilience historically came from the sheer difficulty of submitting. The legal knowledge, the formatting effort, the psychological cost of dealing with bureaucracy. Those were accidental rate limiters. LLMs removed them overnight.
Why this is your problem
You do not work in government. Fine. Look at your public endpoints and ask the paper's two questions.
Does your endpoint accept free-form text through an open digital channel? A support ticket form, a review submit, a claims API, a "contact us" that feeds a human queue. That is exactly the interface profile of 87 percent of the flooding cases. The agent capability required to flood it, quality text generation, is free and ubiquitous.
Was your capacity sized to friction-suppressed demand? Most backends are. Your support team of five handles 800 tickets a week because writing a good ticket is mildly annoying. Cut the annoyance to zero and latent demand surfaces. The paper cites an estimate that about 1 percent of requests to Google Gemini already relate to government interaction. Whatever your domain, assume the same curve: when interaction cost drops, submission volume and verbosity rise.
The researchers also note where the risk concentrates: financially attractive services with complex submission requirements, where friction historically gated who submitted. Translate to private sector: anywhere a successful submission moves money or triggers a legally obligated workflow, refunds, disputes, claims, appeals, takedowns. Those endpoints will be flooded first, because that is where the return on a generated submission is highest.
So what do you do? The paper's response map has two branches, suppress demand or increase capacity, and it warns that the fastest demand-suppression tools, fees and friction, hurt legitimate users most. As an engineer you get a third option the paper only gestures at: make your submission surface structurally expensive to flood without making it expensive to use. Here is how, in Spring Boot.
Defense 1: Rate limit per identity, not per IP
A rate limit is table stakes for quantitative flooding, but the paper's data shows why the naive version fails: submitters are authenticated, real humans acting in good faith, one request at a time. Per-IP limits catch scripted abuse, not a thousand legitimate users each pasting an LLM draft. And agents often rotate anyway.
What actually works is per-identity budgets with a burst allowance, applied at the submission endpoint, not globally. Bucket4j is the standard Java library for this.
First the dependency, using the plain in-memory version for illustration. Production deployments should back it with Redis or Hazelcast so limits hold across instances, via bucket4j-redis:
<dependency>
<groupId>com.bucket4j</groupId>
<artifactId>bucket4j-core</artifactId>
<version>8.14.0</version>
</dependency>
Then a small service that hands each authenticated principal a budget:
@Service
public class SubmissionRateLimiter {
private final ConcurrentHashMap<String, Bucket> buckets = new ConcurrentHashMap<>();
private Bucket newBucket() {
return Bucket.builder()
.addLimit(limit -> limit
.capacity(5) // burst: up to 5 submissions at once
.refillGreedy(5, Duration.ofHours(1))) // refill 5 per hour
.build();
}
public boolean tryConsume(String principalId) {
return buckets
.computeIfAbsent(principalId, id -> newBucket())
.tryConsume(1);
}
}
And the guard in your controller, returning 429 with a Retry-After rather than a silent failure, because legitimate users who hit the limit deserve to know when to come back:
@PostMapping("/api/claims")
public ResponseEntity<?> submitClaim(
@AuthenticationPrincipal AppUser user,
@RequestBody ClaimRequest request) {
if (!rateLimiter.tryConsume(user.getId())) {
return ResponseEntity.status(429)
.header("Retry-After", "3600")
.body(Map.of("error",
"Submission limit reached. Try again later."));
}
// ... process claim
return ResponseEntity.accepted().build();
}
Honest limits: this caps how many requests one identity sends. It does nothing, zero, about one enormous request. That is the qualitative half, and it needs its own defense.
Defense 2: Constrain the interface, cap the complexity
The paper's most quotable engineering finding is buried in its risk matrix discussion: services built on structured, standardized data formats can enable "straight-through" processing of some cases without human intervention, while free-text interfaces turn every submission into human review work. Free text is not just floodable, it is unprocessable at scale.
The 4,000-page letter case is the extreme, but the principle scales down. Every character of unstructured text you accept is processing capacity someone else can spend for free. So cap it.
Hard length caps at the edge. Enforce them before parsing, before validation, before anything expensive:
@Component
public class SubmissionSizeFilter extends OncePerRequestFilter {
private static final int MAX_BODY_BYTES = 32 * 1024; // 32 KB
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain)
throws ServletException, IOException {
if (request.getRequestURI().startsWith("/api/submissions")
&& request.getContentLengthLong() > MAX_BODY_BYTES) {
response.setStatus(413);
response.setContentType("application/json");
response.getWriter().write(
"{\"error\":\"Submission exceeds 32 KB limit\"}");
return;
}
chain.doFilter(request, response);
}
}
Configure the same ceiling in your servlet container so oversized bodies never even buffer fully. For embedded Tomcat in your application properties:
server:
tomcat:
max-http-form-post-size: 32KB
spring:
servlet:
multipart:
max-request-size: 32KB
Prefer structured fields over free text. The deeper fix is interface design. Instead of one "describe your issue" textarea, ask for structured fields: a category enum, a date, an amount, a short description with a 500-character cap. This is the paper's "straight-through processing" point in miniature. A structured claim with a category and an amount can be triaged, auto-routed, or auto-decided. A 4,000-page narrative cannot. The Australian FOI problem and the German court problem are both, at bottom, free-text intake that assumed writing was hard.
Score what remains. If you must accept free text, measure it. Submission length, formatting density, and vocabulary are all signals. The flooding paper's cases entered the dataset precisely because officials noticed anomalous submission patterns. You can notice them too, programmatically:
double risk = 0;
if (text.length() > 2000) risk += 0.4;
if (text.split("\\n\\n").length > 15) risk += 0.25; // many sections
if (countEmDashLikeTics(text) > 20) risk += 0.15;
if (legalTermDensity(text) > 0.02) risk += 0.2; // "pursuant", "hereby", ...
The point is not to detect AI text reliably, you will not, detectors lose that race. The point is to route high-complexity submissions into a slower queue and keep straight-through processing for the rest. The paper explicitly warns that friction applied blindly punishes poor and less digitally literate users first; a complexity score lets you apply friction selectively, to the submissions that actually cost you processing effort, rather than to people.
Defense 3: Identity-gated channels for consequential workflows
The paper's headline recommendation for governments, ahead of fees or rate caps, is integrating digital identity into the most exposed services. Not because identity stops flooding by itself, but because identity-bound submissions cannot scale the way anonymous ones can, and because identity lets you apply per-person policy instead of blunt global policy.
The private-sector translation: your consequential endpoints, anything that moves money or triggers obligated work, should require verified identity and session-bound submissions. In Spring Security terms, this is the difference between:
.requestMatchers("/api/claims/**").permitAll()
and
.requestMatchers("/api/claims/**").authenticated()
.requestMatchers("/api/claims/**")
.access((auth, ctx) ->
new WebAuthenticationDetails(ctx.getRequest())
.equals(sessionBoundDetails(auth.get())))
The real world version of this is less about the code snippet and more about the policy decision: which of your submission channels are anonymous, and what does one anonymous submission cost you? Every anonymous, consequential, free-text endpoint is a flooding surface with no identity lever at all. The paper found governments respond with friction in 17 percent of cases already, and the fastest friction tools, like Japan blocking a comment procedure by IP address, are the crudest ones. Identity binding is what lets you reach for precise tools instead.
One caution the paper makes that transfers directly: CAPTCHA-style friction is a wasting asset. It notes CAPTCHAs no longer reliably identify human visitors, and the flooding cases were mostly humans submitting manually anyway. Do not budget for CAPTCHA as your agentic defense. Budget for identity, structure, and limits.
Defense 4: Log like you will need to explain it later
The researchers could only study flooding because services kept data: annual volumes, submission patterns, per-case records. Your equivalent is an append-only audit trail on submission intake. You want, per submission: identity, timestamp, size, complexity score, channel, and the decision made. Not to be surveillance-heavy, but because the day your queue starts backing up, the question "since when, from whom, and how big" needs an answer you can query, not a guess.
If you want a deep treatment of append-only audit trails in Spring Boot, I wrote one earlier this year, so here I will just leave the schema sketch:
CREATE TABLE submission_audit (
id BIGSERIAL PRIMARY KEY,
principal_id TEXT NOT NULL,
submitted_at TIMESTAMPTZ NOT NULL DEFAULT now(),
body_bytes INT NOT NULL,
complexity DOUBLE PRECISION NOT NULL,
channel TEXT NOT NULL,
decision TEXT NOT NULL
);
CREATE INDEX ON submission_audit (submitted_at);
CREATE INDEX ON submission_audit (principal_id, submitted_at);
With that in place, "qualitative flooding is up 40 percent month over month" becomes a one-line query instead of an anecdote.
The checklist
Here is the save-worthy version. Run it against every public submission endpoint you own.
- Quantitative defense: per-identity token bucket (Bucket4j), 429 with Retry-After, distributed via Redis in multi-instance deployments
- Qualitative defense: hard body-size cap at the filter level, container-level cap as backstop, field-level length caps in validation
- Interface audit: every free-text field is a flooding surface, replace what you can with structured fields and enums
- Complexity routing: score residual free text, route high scores to a slower queue instead of rejecting them
- Identity binding: consequential workflows require authenticated, session-bound submission, never anonymous
- No CAPTCHA dependence: assume bot tests fail, design as if submitters are human and assisted
- Audit trail: append-only intake log with identity, size, complexity, decision, queryable by time
- Latent demand check: ask what your current volume would look like if submitting became effortless, that number is your real capacity requirement
What I would do differently if I were starting today
Design the intake interface as if submission cost were already zero, because it effectively is. Most of us inherited forms whose brevity was enforced by human patience. That enforcement is gone. The services in the flooding dataset were not attacked, they were simply exposed the day the accidental rate limiter of "writing is hard" stopped working. Assume yours will be too, on the timeline of the next model release rather than the next fiscal year.
Have you seen submission volume or verbosity climb on a public endpoint you run since AI assistants went mainstream? What did your team blame it on? I am collecting patterns and I read every comment.
I write about Java, Spring Boot, and AI every week. Subscribe, it is free.
Sources: the study is Characterizing Agentic Flooding of Government Services by Chris Schmitz, Lewis Hammond, and Alan Chan, to appear at AIES 2026. The abstract and full text are on arXiv, and the case dataset is on GitHub. The Hacker News discussion is also worth a read for practitioner reactions.
Top comments (0)