Retry and idempotency cost: paying for the same work twice
Retries are free to configure and expensive to run. Duplicate processing multiplies compute, downstream calls, and side effects. Here is what retry policy really costs and how idempotency changes it.
Quick answer
Every retry pays the full price of the original attempt. Asynchronous Lambda invocations retry twice by default, SQS event source mappings retry until maxReceiveCount is reached, and Step Functions retry per the policy you write. A 512 MB function running 400 ms costs $0.0000034 per attempt, so a 1 percent failure rate with 3 attempts on 100 million invocations adds about $7 in compute but potentially thousands in downstream API and database charges. Idempotency stores cost real money too: a DynamoDB idempotency table doing 2 writes and 1 read per invocation at 100 million invocations costs about $275 a month, which is cheap compared to duplicate side effects but not free.
Distributed systems retry. Serverless platforms make retrying the default, often invisibly, and each retry is a complete re-execution billed at the full rate. What makes retry cost hard to reason about is that the compute charge is usually the smallest part: the downstream calls, the duplicate writes, and the compensating work to undo duplicates dominate.
Where retries come from
| Invocation path | Default retry behaviour |
|---|---|
| Synchronous (API Gateway, Function URL) | None by the platform; client may retry |
| Asynchronous (SNS, EventBridge, direct async) | 2 retries, up to 6 hours |
| SQS event source mapping | Until maxReceiveCount, then DLQ |
| Kinesis or DynamoDB Streams | Retries the shard until success or the record expires |
| Step Functions task | As configured, commonly 3 attempts with backoff |
| AWS SDK inside your code | Typically 3 attempts, often unnoticed |
Those layers compose. A Step Functions task with 3 attempts calling a Lambda that internally retries an SDK call 3 times, triggered by an SQS mapping with maxReceiveCount 5, can produce 45 attempts at the deepest layer for one logical unit of work. Nobody designs that; it accumulates from defaults.
What retries cost in compute
Take 100 million invocations a month, 512 MB, 400 ms, with a 1 percent failure rate and 3 total attempts per failure.
| Line | Volume | Cost |
|---|---|---|
| Successful invocations | 99,000,000 | $349.80 |
| Extra attempts on failures | 2,000,000 | $7.07 |
| Extra CloudWatch Logs (2 KB each) | 4 GB | $2.00 |
| Extra SQS receives | 2,000,000 | $0.80 |
Under $10 for the retries themselves. This is why retry policy is rarely questioned on cost grounds. The problem is what the retries touch.
The downstream multiplier
If each invocation makes 3 DynamoDB writes, 2 million extra attempts means 6 million extra write request units at $1.25 per million, or $7.50. Manageable. If each invocation calls a metered third-party API at $0.002 per call, 2 million extra attempts is $4,000. If each invocation triggers a downstream Lambda chain of four functions, the retry cost multiplies by the whole chain. If it sends an email or a webhook, duplicates become a customer-facing problem, and the cost of handling that is measured in support time rather than dollars per million.
| Downstream per invocation | Cost of 2M extra attempts |
|---|---|
| 3 DynamoDB writes | $7.50 |
| 1 Bedrock or ML inference call | Hundreds to thousands |
| 1 metered API call at $0.002 | $4,000 |
| 4-function chain, 200 ms each | $28 plus its own downstreams |
| 1 transactional email | Duplicate messages to customers |
What idempotency costs to add
The standard pattern is a DynamoDB table keyed by an idempotency key, with a conditional write to claim the key and a record of the result. That is typically one conditional write on entry, one update on completion, and one read on a duplicate. At 100 million invocations a month with on-demand pricing, 200 million writes cost $250 and reads add roughly $25, so about $275 a month plus a small storage charge with a TTL keeping the table trim.
That is real money, and it is worth comparing against the duplicate cost it prevents. If your downstream is 3 DynamoDB writes, the idempotency table costs 30 times more than the duplicates it avoids and you should probably make the writes naturally idempotent instead, using conditional expressions or deterministic keys. If your downstream is a metered API at $0.002 per call, the table pays for itself 14 times over.
Cheaper idempotency
Natural idempotency is free. A write keyed by a deterministic id, a conditional update, or an upsert produces the same state on the second attempt with no extra infrastructure. Where a ledger is required, consider DynamoDB provisioned capacity for the idempotency table, since its traffic is exactly as predictable as your invocation volume, which typically cuts that $275 to well under $100. ElastiCache Serverless is another option, billed from about $0.084 per GB-hour of stored data plus $0.0034 per million ECPUs, which can be cheaper at very high volumes.
Tuning the policy
Retry only what is retryable. A validation failure or a 400 response will fail identically every time, so retrying it three times triples the cost of a guaranteed failure. Classify errors and send permanent ones straight to the dead letter path. Use exponential backoff with jitter so retries do not synchronize into a second wave that hurts the dependency that is already struggling. Cap total attempts at 3 for most paths. And disable SDK-level retries where an outer layer already retries, since nested policies multiply rather than add. The failure path deserves the samecost scrutiny as the happy path. Price the chain, retries included, against the resource catalog.
FAQ
How many times does Lambda retry by default?
Asynchronous invocations from SNS, EventBridge, or direct async calls retry twice by default, over a window of up to 6 hours. Synchronous invocations are not retried by the platform, though clients often retry themselves. SQS event source mappings retry until maxReceiveCount is reached, and stream sources retry the shard until success or record expiry.
Why do retry policies multiply rather than add?
Because each layer applies its own policy to the layer below. A Step Functions task with 3 attempts calling a Lambda whose SDK retries 3 times, triggered by an SQS mapping with maxReceiveCount 5, can produce up to 45 attempts at the deepest layer for one logical unit of work. This usually accumulates from defaults rather than being designed.
How much do retries actually cost in compute?
Less than most people expect. For 100 million invocations a month at 512 MB and 400 ms with a 1 percent failure rate and 3 attempts, the extra 2 million attempts cost about $7 in duration, $2 in logs, and under $1 in queue requests. The compute side of retry cost is rarely the problem.
What makes retries expensive if not compute?
The downstream calls. Two million extra attempts costs $7.50 if each invocation does 3 DynamoDB writes, but $4,000 if each calls a metered third-party API at $0.002 per call, and far more if each triggers a model inference. Retries that send emails or webhooks also create duplicate customer-facing side effects whose cost is measured in support time.
What does an idempotency table cost?
A DynamoDB idempotency table doing one conditional write on entry, one update on completion, and occasional duplicate reads costs about $275 a month on-demand for 100 million invocations, mostly the $250 for 200 million writes. Switching that table to provisioned capacity, since its traffic tracks invocation volume exactly, usually brings it under $100.
How does C3X help with retry and idempotency cost?
C3X prices the functions, queues, and tables in an event pipeline from Terraform, including the idempotency store, so the infrastructure cost of a reliability pattern is visible at review time. Because retry settings such as maxReceiveCount and timeouts live in Terraform too, their cost implications can be weighed before they are deployed.
What to do next
Price the failure path alongside the happy path. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.
Share this post
Try C3X on your own Terraform
Free and open source. No API key required. One command to install, one command to estimate.