AlgoInsight

Free lesson · AWS Fundamentals

Service quotas and the limits that bite in production

Easy7 min read

Two Kinds Of Limit

Every AWS service enforces limits, and they come in two flavours that behave completely differently.

Adjustable quotas (soft limits). A default ceiling that AWS will raise on request. Most account- and Region-level limits are of this type: number of VPCs, number of Elastic IPs, EC2 vCPUs per instance family, Lambda concurrent executions. You raise them through the Service Quotas console or API, or a support case. Approval takes anywhere from minutes to days depending on the size of the increase.

Hard limits. Architectural constraints that cannot be raised at any price, because they are properties of how the service is built. The maximum size of an SQS message. The maximum runtime of a Lambda function. The number of IP addresses in a subnet. These are not negotiations - they are design inputs.

Important: The distinction is the whole point. A soft limit is an operational task: file a request, wait, proceed. A hard limit means your design is wrong and you need a different one. Confusing the two costs you either a support ticket you did not need or a rewrite you did not plan for.

Quotas are also scoped. Most are per-account per-Region. Some are per-resource (rules per security group), some are per-Region-wide-across-accounts in an Organization, and a handful are global. Expanding into a new Region starts you at defaults again - this catches teams during disaster recovery tests and multi-Region launches constantly.


The Limits That Actually Bite

The list of AWS quotas runs to thousands of entries. The ones below cause the overwhelming majority of real production incidents.

Warning: All specific numbers below are defaults at the time of writing and change frequently. Verify every one against the Service Quotas console or the service's documented quotas page before designing against it. Treat the shape of each limit as durable and the number as perishable.

Limit Typical default Why it hurts
Lambda concurrent executions 1,000 per Region, account-wide One runaway function starves every other function in the account
EC2 vCPU quota Per instance family, per Region Scale-out stops mid-incident; error is a launch failure, not a warning
VPCs per Region 5 Multi-environment-per-account designs hit this early
Elastic IPs per Region 5 Blocks NAT Gateway and instance provisioning
Rules per security group / SGs per ENI ~60 rules, 5 SGs Microsegmentation designs run out of room
S3 request rate ~5,500 GET, ~3,500 PUT per second per prefix Not per bucket - prefix design determines throughput
DynamoDB per-partition throughput ~3,000 RCU, ~1,000 WCU A hot partition throttles while the table looks under-provisioned
API Gateway throttle ~10,000 RPS per Region, with a burst allowance Applies across all APIs in the Region, not per API
CloudFormation resources per stack ~500 Monolithic templates hit the wall; nested stacks are the answer
ENIs per instance Varies by instance type Constrains pod density on EKS with the VPC CNI
Route 53 records per hosted zone Large, adjustable Rarely hit, but dynamic-record architectures can

Three of these deserve special attention because they behave unlike the others.

Lambda concurrency is account-wide and shared. Every function in the Region draws from the same pool. Reserved concurrency carves out a guaranteed slice for a critical function and caps it - reserving 200 for your payment function guarantees it 200 and limits it to 200. Both halves are the point.

S3 request rate scales per prefix, not per bucket. A bucket with all objects under logs/ has the throughput of one prefix. Spreading keys across many prefixes multiplies available throughput. S3 also automatically partitions as request patterns emerge, but that adaptation takes time - a sudden burst against a single prefix throttles first and adapts later.

DynamoDB partition throughput is invisible in the console. Table-level provisioned capacity is divided across partitions. A table provisioned for 10,000 RCU with all traffic hitting one partition key throttles at roughly 3,000 RCU while reporting healthy table-level utilisation. This is the hot-key problem, and it is a data-modelling failure that looks like a capacity failure.


What Throttling Looks Like

graph TD
    A[Client request] --> B{Within quota?}
    B -->|Yes| C[Request served]
    B -->|No| D[HTTP 429 / ThrottlingException]
    D --> E{Client retries?}
    E -->|No backoff| F[Retry storm<br/>load increases]
    F --> B
    E -->|Exponential backoff + jitter| G[Spread retries over time]
    G --> B
    E -->|Retries exhausted| H[Error surfaces to user]
This diagram shows what happens when a request meets a quota. A client request is checked against the quota. If within quota, the request is served. If not, the service returns an HTTP 429 or a throttling exception. The client then either retries without backoff, which creates a retry storm that increases load and makes the problem worse, or retries with exponential backoff and jitter, which spreads retries over time and allows recovery, or exhausts its retries and surfaces an error to the user.

The failure signature to recognise: ThrottlingException, TooManyRequestsException, RequestLimitExceeded, ProvisionedThroughputExceededException, or HTTP 429. These mean you hit a rate limit, not that the service is broken.

Tip: Exponential backoff with jitter is not optional. Plain exponential backoff synchronises clients - everyone retries at the same doubling intervals and the retry waves keep colliding. Adding randomness to each wait spreads them out. The AWS SDKs implement this by default; hand-rolled retry loops usually do not, and a hand-rolled retry loop is how a small throttle becomes an outage.


Operating Quotas Properly

Discover them. The Service Quotas console lists current values, defaults, and whether each is adjustable. It is also an API, so you can inventory quotas programmatically across accounts and Regions.

Monitor them. Many quotas publish CloudWatch usage metrics. Alarm at 70–80% of the quota, not at 100% - a quota increase request that requires human approval is not something you want to file during an incident.

Pre-raise them. Before a launch, a load test, a new Region, or a DR exercise, request increases in advance. Quota increases are not instantaneous and large ones may be reviewed by a human.

Standardise them. In an AWS Organization, quota request templates apply a set of increase requests automatically to every newly created account. Without this, every new account starts at defaults and every team rediscovers the same limits.

Design within them. Reserved concurrency for critical Lambdas. Prefix design for S3 throughput. Partition key design for DynamoDB. Nested stacks for CloudFormation. These are architectural responses, not tickets.


Common Failure Modes

Warning: The DR test that fails. Failover to a secondary Region succeeds until the ASG tries to launch beyond the default vCPU quota there. The primary Region's raised quotas do not transfer. Quota parity across Regions must be verified as part of the DR runbook.

Lambda concurrency starvation. A batch function scales to consume the account-wide pool; the customer-facing API's function gets throttled. Nothing in either function's configuration hints at the coupling.

The scale event that stops halfway. Traffic spike, ASG scales, hits vCPU quota, launch failures appear in the ASG activity log while CloudWatch shows healthy instances. The alarm you need is on launch failures, not on instance count.

Retry amplification. Client retries on throttle without backoff, multiplied across a fleet, turn a brief limit breach into sustained overload.

Silent quota consumption. Deleted CloudFormation stacks that failed to clean up, orphaned ENIs from deleted Lambdas in VPCs, and unattached Elastic IPs consume quota invisibly.


Why This Matters In An Interview

Interview: What interviewers are listening for:

  • You know limits exist and name at least one specific, correct one at the right moment. "DynamoDB gives about 3,000 RCU per partition, so this partition key would throttle" is a sentence that changes how the rest of the interview goes.
  • You distinguish soft from hard limits and respond to each appropriately.
  • You mention backoff and jitter when discussing retries, unprompted.

Common follow-ups:

  • "Your Lambda function suddenly starts throttling but you didn't change it. Why?" → Account-wide concurrency pool shared with another function. Diagnose via the Throttles metric and concurrent-execution metrics across all functions.
  • "How do you design an S3 key scheme for a high-throughput ingest pipeline?" → Distribute across prefixes; avoid a monotonically increasing date prefix that concentrates all writes on one partition at a time.
  • "What do you do when you hit a hard limit?" → Redesign. Then name a specific example - SQS message size limits push you to the claim-check pattern, storing the payload in S3 and passing a reference.

Practice

Exercise: Starter. Open the Service Quotas console. Find your Lambda concurrent execution quota, your VPC quota, and your EC2 vCPU quota for one instance family. Note which are adjustable.

Intermediate. Pick a service you use and list every quota that your current architecture would hit if traffic increased tenfold. Identify which are soft and which force a design change.

Advanced. Write the quota section of a launch readiness checklist for a new Region: which quotas to verify, what the target values are, how far in advance to request them, and which CloudWatch alarms must exist before go-live.


Related Topics

Back to AWS Fundamentals