What Does API Gateway Cost at Scale?

API Gateway looks free at low traffic, then expensive at scale. REST and HTTP APIs bill per request, and caching and data transfer add more on top.

Published September 2, 2026 · Last updated September 5, 2026

Nobody budgets for API Gateway on day one. It is pay-per-request with no idle charge, so a new API looks free right up until it isn't — and the moment it shows up as a real line item is almost always the moment traffic grew, which means the team just succeeded at the thing they were trying to do. That timing makes the bill feel like a tax on growth, and the natural next question is whether $3.50 per million requests is actually reasonable or whether something in how the API is built is making it worse than it needs to be. Usually it's some of both.

Why does API Gateway charge per request instead of a flat fee?

API Gateway is metered because there's no server to size. You aren't paying for an instance sitting there waiting for traffic — you're paying per request received, which is why the bill tracks usage so closely and why it can look negligible for months and then double the month a marketing campaign lands.

The complication is that "API Gateway" isn't one priced product. AWS sells three different API types under that name, and they meter differently:

  • REST APIs — the original product, with the fullest feature set: request/response transformation, API keys and usage plans, WAF integration, resource policies, and edge or regional endpoints.
  • HTTP APIs — a newer, lighter product for the common case: a proxy in front of Lambda or another HTTP backend, with less built-in tooling and a lower price.
  • WebSocket APIs — for persistent, bidirectional connections, billed on messages sent and on how long connections stay open, not on request count.

Picking the wrong one for the job is the single biggest lever on this bill, and it's a decision most teams made once, early, without revisiting it as traffic grew.

What does API Gateway actually cost per million requests?

Here are AWS's published rates, tiered by monthly volume:

API typeFirst tierNext tierFurther tiers
REST API$3.50 per million requests$2.80 per million$2.38 per million at the highest volume tier
HTTP API$1.00 per million (first 300M/month)$0.90 per million
WebSocket API — messages$1.00 per million messages
WebSocket API — connections$0.25 per million connection-minutes

A REST API and an HTTP API doing the exact same job are not close in price — REST runs roughly 3.5x HTTP's rate at the entry tier. For a service that started as a REST API because that's what the first tutorial used, and never had a reason to revisit it, that multiplier compounds with every month of traffic growth.

Three costs outside the base request rate are easy to miss:

  • Data transfer out — standard AWS data-transfer rates apply, currently $0.09 per GB to the internet. A REST API returning large JSON payloads pays this on top of the per-request fee.
  • Caching (REST APIs only) — an optional response cache, billed hourly by size regardless of traffic. AWS's own example prices a 1.6 GB cache at $0.038/hour — roughly $27/month whether it's saving you money or sitting there unused.
  • Free tier — new accounts get 1 million REST API calls, 1 million HTTP API calls, and 1 million WebSocket messages plus 750,000 connection-minutes per month, for the first 12 months. After that, or once you're past a million calls in a month, every one of the rates above applies from request one.

How do I find out which API and stage is driving the bill?

Start in Cost Explorer, filtered to API Gateway and grouped by Usage Type. That split separates the request charge from data transfer and caching in one screen, which tells you whether you're chasing request volume or something else entirely.

To see which specific API and stage is generating the most traffic, pull the Count metric per API:

aws cloudwatch get-metric-statistics \
  --namespace AWS/ApiGateway \
  --metric-name Count \
  --dimensions Name=ApiName,Value=checkout-api Name=Stage,Value=prod \
  --start-time "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ)" \
  --end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
  --period 86400 \
  --statistics Sum \
  --region us-east-1 \
  --output table

Run that per stage across your APIs and the distribution usually looks like everything else on an AWS bill: one or two chatty APIs — often an internal service-to-service one nobody thinks of as "external traffic" — account for most of the total. To confirm which API type each one is, aws apigateway get-rest-apis and aws apigatewayv2 get-apis list REST and HTTP/WebSocket APIs separately, since they live in different API surfaces even inside the same console.

How do I bring the bill down without breaking clients?

Move REST APIs that don't need REST-only features to HTTP APIs. If an API isn't using request/response transformation, resource policies, edge-optimized endpoints, or WAF at the API Gateway layer, it's paying REST pricing for HTTP API functionality. AWS's own migration guidance puts typical savings at up to 70% on the request charge alone for a straight proxy-to-Lambda pattern.

Turn off caching you aren't measuring. REST API caching bills by the hour regardless of hit rate. If nobody has checked the cache hit ratio in CloudWatch recently, there's a real chance it's costing more than the backend calls it's supposed to be saving.

Cache values in the client instead of re-fetching them. The same "call it once, hold it in memory" fix that cuts a chatty backend's API-call costs elsewhere applies here too: a mobile client or downstream service that polls an endpoint every few seconds for data that changes hourly is buying request volume it doesn't need.

Use usage plans and throttling to cap runaway callers. A usage plan with a rate limit turns a misbehaving integration partner or a retry loop with no backoff into a controlled cost instead of an open-ended one, and it protects your backend at the same time.

Batch requests where the client controls the pattern. An API called once per item in a list, a hundred times a page load, pays the per-request fee a hundred times over. A single batched call with the same payload pays it once.

What else should I check while I'm in here?

If your API receives webhook deliveries from SNS — a common pattern for fanning events out to external HTTP endpoints — every SNS delivery attempt to that endpoint is also a billable API Gateway request, on top of whatever SNS itself charges to publish and deliver the message. See what SNS actually costs to send for the meter driving that traffic in the first place.

If your API's backend is a Lambda function reading a value from Secrets Manager on every invocation, you're stacking two per-request meters on top of each other — the API Gateway request charge and the Secrets Manager API-call charge — for a value that probably doesn't change between requests. Fixing the Lambda's caching fixes both bills at once.

Custom domains in front of API Gateway also usually mean a Route 53 hosted zone and health checks sitting upstream of the API, each billing on its own schedule regardless of how the API itself performs — see how Route 53 pricing adds up for what those cost on their own.

More broadly, a per-request meter that grows quietly with traffic is exactly the shape that a lot of an AWS bill takes — see the wider pass over what a growing AWS bill usually hides for the rest of the list, worked through service by service.

How do I catch this before it becomes a real number?

An API Gateway bill rarely jumps — it climbs in step with legitimate traffic growth, which is precisely why it's easy to write off as "the cost of success" instead of checking whether the API type, caching, and client call patterns behind it are still the right choices. That's a comparison against your own history, not an absolute threshold, which is exactly what a spike detector misses and a recurring audit catches.

Connect your AWS account read-only and Parsivex's daily anomaly checks compare every service's spend — API Gateway included — against its own trailing baseline, so a genuine step change (a client that started retrying without backoff, a cache that got disabled and nobody noticed) surfaces the next morning instead of buried in a monthly total. For how those daily checks and severity thresholds work, see cost anomaly alerts, or read how scans work for what a connected account scan reads across the rest of your bill.