What dunning recovery costs
This is one of the cheapest systems in the series, and the reason is worth stating plainly: the part that recovers the money — the retry schedule — is free, because it’s plain Python doing date arithmetic. The whole bill is a few small variable lines on top of one fixed cost. This post breaks down exactly where the $1.90 a month goes, and what changes when you run ten times the volume.
Key takeaways
- About $1.90/month at ~150 active subscriptions and ~30 failed charges a month.
- The biggest single line is Secrets Manager — three secrets at $0.40 — because the actual work is so cheap.
- The part that recovers the money, the retry schedule, is free: it’s plain Python doing date arithmetic.
- No always-on compute, no NAT Gateway, no API Gateway — the variable cost is pennies.
- At ten times the volume it lands around $4.90, because the fixed Secrets Manager cost doesn’t grow.
The breakdown, line by line
The headline is almost funny: the single most expensive thing in a payment-recovery system is the place it keeps its passwords. At small-business volume — take ~150 active subscriptions, ~30 charges failing in a month, and around 75 dunning emails sent as those failures work through the retry schedule — here’s where every cent of the ~$1.90 goes.
| Service | What it does here | Monthly |
|---|---|---|
| Secrets Manager | 3 secrets × $0.40 — processor API key, webhook secret, link-signing key | $1.20 |
| CloudWatch Logs | All Lambdas, structured JSON, 7-day retention | $0.30 |
| Bedrock (Haiku 4.5) | One small copy call per dunning email + the monthly report | $0.20 |
| Lambda | Webhook, scheduler, retrier, mailer, gatekeeper, sweep — all arm64, short | $0.05 |
| DynamoDB (on-demand) | Dunning state, audit log, dedupe — a few hundred small writes | $0.05 |
| EventBridge Scheduler | One-off retry rules + the daily sweep (~100 invocations) | $0.03 |
| SES (outbound) | ~75 dunning emails at $0.10 per thousand | $0.02 |
| S3 | Email templates, logo, monthly report — a few MB | $0.02 |
| SQS (+ DLQ) | Buffers webhook events — a few hundred messages | $0.01 |
| AWS Budgets | First two budgets are free | $0.00 |
| Total | ~$1.90 |
Where the dollars actually go
Secrets Manager (the bulk). Three secrets, each $0.40 a month, is $1.20 — almost two-thirds of the bill. That feels like a lot until you remember what they protect: the API key that can charge cards, the webhook secret that authenticates the processor, and the key that signs update-card links. Rotating them, scoping them per-Lambda, and keeping them out of environment variables is exactly where you want to spend a dollar. If you really wanted to trim it you could fold the link-signing key into Parameter Store (free for standard parameters), but the saving is $0.40 and the convenience of one secrets story isn’t worth losing.
Bedrock (one small call per email). Each dunning email is a few hundred tokens in and a few hundred out on Haiku 4.5 — a fraction of a cent. Across ~75 emails it’s well under twenty cents, and the monthly recovery report adds one slightly larger call. The retry schedule, the charge, and the pause all run with no model at all, so AI is a rounding error here, not a driver.
Lambda, DynamoDB, Scheduler, SES, SQS, S3 (pennies, together). This is the whole working machine, and it costs less than a dollar combined. The functions are short and arm64; the tables take a few hundred small writes; the one-off schedules fire ~100 times; the emails are $0.10 per thousand. None of it is rounding up to anything meaningful at this volume.
What doesn’t cost money
- API Gateway. Replaced by Lambda Function URLs for the webhook receiver and the entitlement check.
- NAT Gateway. Nothing runs in a VPC. No NAT, no $32/month minimum.
- Always-on compute. No EC2, no Fargate. The system uses zero compute in the days between one customer’s retries.
- A scheduler that’s always running. No cron table to poll. Each retry is a one-off EventBridge Scheduler rule that self-deletes after it fires.
- Models on the money path. The schedule, the charge, and the pause are plain Python. Bedrock only writes email copy.
How the cost scales
At ten times the volume — around 1,500 subscriptions and 300 failed charges a month — the bill is about $4.90, not $19. The reason is the fixed/variable split in Fig 6: Secrets Manager stays at $1.20 no matter how many charges fail, while CloudWatch Logs, the per-email Bedrock calls, and the per-event Lambda and DynamoDB work scale with the number of failures. Logs tend to be the line that grows fastest, so structured-but-lean logging and the 7-day retention matter. Past a few thousand subscriptions you’d look at batching log delivery and at a provisioned-concurrency review — but those are tuning, not a redesign. The retry schedule never becomes the cost, because it never costs anything.
Set an AWS Budgets alarm at $10/month so anything unusual pages you before it matters. The recovered revenue dwarfs the bill at any volume: one saved £29 subscription pays for more than a year of running the whole system.
Last post in the series: the engineering reference. Same system, drawn for engineers — service names, the Lambda inventory, IAM scopes, DynamoDB schemas, the SES setup, the Bedrock model id, and the EventBridge Scheduler config.
All posts