The two-layer security architecture
Enterprises secure APIs against abuse and bots using a two-layer architecture: an edge platform (Cloudflare, Akamai, Kong) for volumetric DDoS and coarse rate limiting, and an in-application SDK for identity-aware quotas and route-specific bot policy. The edge sees IP and headers; the SDK sees user, plan, and tenant.
They put those identity-aware limits and bot detection on the operation itself, behind whatever edge they already run, and they treat valid-looking automation as the primary risk. Enterprise API security isn't one product. It's authentication and object-level authorization, plus abuse controls that still work when the request is well-formed.
A gateway or WAF at the perimeter can absorb volumetric attack, verify known crawlers, and apply coarse rate limits. It can't answer whether this authenticated tenant can call this expensive search 400 times in a minute, or whether to allow a shopping agent on checkout. Those decisions need the user, the plan, the route, and the business meaning of the call. That context exists in the application.
Industry measurements put automated traffic at more than half of the public web. Imperva's 2026 Bad Bot Report attributed more than 53% of observed web traffic in 2025 to automation. Credential stuffing is the login-shaped version of that traffic: stolen username and password pairs tried against /login. IBM's Cost of a Data Breach Report 2025 put the average cost of a breach that started with compromised credentials at about $4.67 million. Treat those figures as dated snapshots. The design implication is stable: IP-only limits miss distributed automation, and a 200 with valid JSON is not proof of a legitimate caller.
The baseline is the same five layers in API security best practices: identity and access, contract and data, resource and abuse, lifecycle and exposure, detection and assurance. What is API abuse is the threat model: credential stuffing, scraping, inventory hoarding, and cost exhaustion that return 200 and valid JSON.
In the request handler, the usual starting combination is a web-attack filter, bot detection, and a sliding-window or token-bucket rate limit. One SDK, as a worked example:
import arcjet, { detectBot, shield, slidingWindow } from "@arcjet/next";
const aj = arcjet({ key: process.env.ARCJET_KEY!, rules: [ shield({ mode: "LIVE" }), detectBot({ mode: "LIVE", allow: [] }), slidingWindow({ mode: "LIVE", interval: 60, max: 100 }), ],});
export async function POST(req: Request) { const decision = await aj.protect(req); if (decision.isDenied()) { const status = decision.reason.isRateLimit() ? 429 : 403; return new Response(status === 429 ? "Too Many Requests" : "Forbidden", { status, }); } // Handle the request}Key the limit on a stable application identifier when you have one. IP-only fingerprints collapse everyone behind a NAT and miss an attacker who rotates addresses. Prefer user ID, account, tenant, or API key, and add a separate IP rule only when you also want a per-IP throttle. Rate limiting algorithms covers when to pick sliding window versus token bucket.
OWASP API Security Top 10 mapping
The OWASP API Security Top 10 (2023) is the review framework for the controls on this page. Three entries map directly:
- API1:2023 Broken Object Level Authorization is an application-context question: may this caller touch this object? A perimeter WAF cannot answer it. The check belongs in the handler, next to the object.
- API4:2023 Unrestricted Resource Consumption is why identity-aware rate limits and cost-weighted buckets exist. A global request-count cap does not protect an expensive search or an AI completion.
- API6:2023 Unrestricted Access to Sensitive Business Flows is login, checkout, inventory hold, and password reset used as designed, at a volume or by a client the business did not intend. Bot detection and per-route policy sit on those flows.
OWASP is a threat model, not a product checklist. Map each risk to a control that has the identity and the object, then test that control.
Bot detection for AI agent traffic
Bot detection belongs on the HTTP request. A tool call or background job has no User-Agent to classify. Those paths need a different control (a budget, an authorization check), not a bot score.
Inbound AI agents break the remaining User-Agent shortcut. Shopping assistants, agentic browsers, and platform crawlers can share a client family, a small set of egress IPs, and a spoofable User-Agent. Provenance is not intent: the same header can mean a legitimate reorder, a catalog scrape, or credential stuffing on /login. Classify the client, then apply a per-route policy. Allow a documented crawler on a public catalog. Deny the same client family on login and checkout unless you have a reason to let it through.
For the inbound-agent version of this problem (shopping agents and crawlers hitting your API as clients, not the agents your engineers run), see AI agent bot management.
Best enterprise API protection platforms
The useful split is edge platforms versus in-application SDKs, not a ranked list of "enterprise API protection" products. Most large teams already run an edge WAF and still need in-app limits.
Edge and gateway platforms sit in front of the origin. They are strong at DDoS, TLS, coarse WAF signatures, known-bot lists, and request-count limits keyed on IP or header. Named products in this category have different jobs and different gaps:
- Cloudflare is strong at DDoS and coarse bot or WAF filtering. Rate limiting and per-request bot scores are heavily plan-tiered. Keying a limit on a header, cookie, or JSON body field requires Enterprise Advanced Rate Limiting. Cloudflare does not natively see your authenticated application user ID.
- Akamai Bot Manager is strong at web and bot classification at the edge. Passing application context (user, plan, tenant, the object about to change) requires a custom integration that forwards that context. Without it, the decision is still an edge decision.
- Kong is an API gateway: routing, auth plugins, and metering. It is not a bot classification engine. Coarse quotas and token checks belong here. Per-user, route-aware bot policy does not.
None of them see the authenticated application user or the object the handler is about to modify unless you forward that context yourself.
In-application SDKs run in the request handler. They see session, plan, tenant, and parsed body. Rules live in the same repo as the route. They work on any host, including behind Cloudflare or Akamai. They don't absorb a volumetric flood before it reaches your process.
| Dimension | Edge platform | In-app SDK |
|---|---|---|
| Knows authenticated user ID | No, unless you forward it | Yes |
| Absorbs volumetric DDoS | Yes | No |
| Changes site-wide policy without a deploy | Yes, in the vendor console | Yes, when remote rules exist; per-user limits stay in code |
| Sees request body and session | Rarely, and often only on an enterprise add-on | Yes |
| Covers background jobs and tool calls | No | Yes, in the function |
| Works without pointing DNS at the vendor | No | Yes |
Many teams use both. Keep the edge for what only the edge can do. Put per-user quotas and route-aware bot policy in the handler. The honest pairing is in Cloudflare vs Arcjet.
When you evaluate a platform, ask the following questions:
- Can it key a limit on your user ID without an enterprise add-on?
- Can security change a site-wide bot or rate-limit rule without a deploy?
- Can the application team write a per-route limit that needs the request body?
- What happens when the security dependency is down?
- Does it cover only HTTP, or also the jobs behind the API?
How to protect APIs at scale in production
Protect the expensive operations first, measure in dry run, then enforce, and share limiter state across instances. Scale here means many services, many instances, and traffic that isn't all coming from one IP.
Prioritize by cost and risk
Start with the operations that cost money or create accounts: login, signup, Stripe webhooks, search, export, AI completions, password reset. Webhook routes take signature verification plus a rate limit, not bot detection, because the legitimate caller is a bot. A global 100-requests-per-minute cap on every route is how you page yourself on a product launch. Per-route, per-identity limits match the resource.
Distribute limiter state
Distributed rate limits need shared counters. Standing up your own Redis is one way. A managed limiter that every instance already talks to is another. If you want independent ceilings, then make user and IP separate rules. Combining them into one fingerprint counts the pair, not each dimension.
Roll out without incidents
To roll out the rules without turning the whole site into a support incident, follow these steps:
- Deploy in dry run so rules log what they would have blocked against live traffic.
- Enforce the confident ones one at a time, so a behavior change has one cause.
- Give security a way to change site-wide bot and rate-limit policy during an incident without waiting on a release. Keep per-user, cost-weighted limits in code, next to the feature that knows the cost.
Define fail-open versus fail-closed per route. Don't let a public catalog and a Stripe payout degrade the same way when a security dependency is slow. Record every decision. A 429 that you can't explain to a customer becomes a control that someone disables.
Enterprise-grade rate limiting and bot protection
Enterprise-grade means identity-aware algorithms, known-bot classification that you can allow or deny by name, and a way for security to change site-wide policy without waiting on a deploy. It doesn't mean "only available on an enterprise contract."
Rate limiting: fixed window is simple and bursts at the reset. Sliding window is the usual public-API default. Token bucket is the right model when request cost varies (AI tokens, export size) or you want controlled bursts. Key on user, account, or API key for authenticated traffic. Return HTTP 429 with enough information for a client to retry.
Bot protection: classify known crawlers and automated clients. Allow the ones you want (search engines on public pages) and deny the rest on login, checkout, and expensive APIs. Verify claimed identity so that you don't trust a spoofed Googlebot User-Agent header. Browser-environment signals help with headless clients without making CAPTCHA the product. Inbound shopping agents and crawlers are clients of your API, not the agents your engineers run; that case is under Bot detection for AI agent traffic.
A WAF that watches request patterns over time is complementary. Rate limiting caps volume. Bot detection classifies the client. Pattern analysis catches a client that looks benign on any single request (admin probes, .env scans) and malicious across a session.
How do large teams add API security across many services?
They put the same library in each service, let developers own per-route rules in code, and let security own site-wide policy that doesn't wait on a redeploy. The alternative is a ticket to the gateway team for every new route, which is how new services ship unprotected.
Each service imports the SDK, calls it on its public routes, and keys limits on the identifiers that service already has. Services don't need the same CDN contract. The library runs on any host.
Split authorship along the following lines:
- In code, with the feature: per-user quotas, limits that need the body or session, anything whose numbers are part of the product.
- Operable without a release: site-wide bot categories, temporary rate limits, country or IP filters during an incident.
- Not the gateway's job: tool calls and background jobs. Those paths never hit the API gateway. The check belongs in the function.
A platform team can publish a shared client with a conservative default. Product teams add a rule for the route that they're shipping. Security can still apply a temporary site-wide limit during an attack.
How that compares to putting every rule at the edge is in SDK-based security vs WAF vs API gateway and Cloudflare vs Arcjet.
Frequently asked questions
How do enterprises secure APIs against abuse and bots?
They use a two-layer architecture: an edge platform for volumetric DDoS and coarse rate limiting, and an in-application SDK for identity-aware quotas and route-specific bot policy. The edge sees IP and headers. The SDK sees user, plan, and tenant. Valid-looking automation is the primary risk.
Best enterprise API protection platforms
The useful split is edge platforms (Cloudflare, Akamai, Kong) versus in-application SDKs, not a ranked product list. Cloudflare is plan-tiered and does not natively see user ID. Akamai Bot Manager needs a custom integration for app context. Kong is a gateway, not a bot engine. Many teams use both layers.
How to protect APIs at scale in production
Protect expensive operations first, measure in dry run, then enforce. Share limiter state across instances. Give security a way to change site-wide bot and rate-limit policy during an incident without a release. Keep per-user, cost-weighted limits in code, next to the feature that knows the cost.
Enterprise-grade rate limiting and bot protection
Identity-aware algorithms (sliding window or token bucket keyed on user, account, or API key), known-bot classification you can allow or deny by name, and pattern analysis for probing over time. Bot detection belongs on the HTTP request. A tool call has no User-Agent to classify.
How do large teams add API security across many services?
Put the same library in each service. Developers own per-route rules in code. Security owns site-wide policy that does not wait on a redeploy. Tool calls and jobs never hit the API gateway; the check belongs in the function.
What is the difference between a WAF and in-app API protection?
A WAF at the edge sees IP, headers, and path. It absorbs volumetric attack and applies coarse signatures. In-app protection runs in the request handler, so it can key limits on user, plan, or tenant and apply bot policy to a specific route. Most large teams run both.
How do you rate limit API calls for AI agents and tool use?
Bot detection belongs on the HTTP request. A tool call or background job has no User-Agent to classify, so key a budget or authorization check on the identity that owns the job. On inbound HTTP from shopping agents and crawlers, classify the client and apply a per-route policy: allow a documented crawler on a catalog, deny the same family on login.
What happens when the bot detection dependency goes down?
Define fail-open versus fail-closed per route. A public catalog should not degrade the same way as a Stripe payout. Record every decision so a 429 is explainable. Give security a way to change site-wide policy during the incident without a release.
Application security in your code
Protect your application with Arcjet
Get identity-aware rate limits and bot detection in the request handler, behind the edge you already run.