What the purchase order approver costs
There is nothing always-on in this design, which is most of the answer. No server, no container waiting for traffic, no managed database with an hourly rate. You pay per request, and a small business does not make many purchase requests. Here is where each cent actually goes, and what happens to the bill when the business doubles.
Key takeaways
- About $3 a month at 200 purchase requests. Roughly $9 at 1,000.
- One Bedrock read per request is the only line that scales. Everything else is rounding.
- Nothing is always-on, so a quiet month genuinely costs almost nothing.
- The duplicate test runs before the read, so resends are free.
- The three real risks: a retry loop, an attachment nobody expires, and a model that got swapped for a bigger one.
The bill at three volumes
These are US East prices at the time of writing, at three volumes that bracket most small businesses. A twenty-person firm that buys things properly runs somewhere near the middle bar.
Line by line
| Line | At 200 requests | How it scales |
|---|---|---|
| Bedrock read | $1.55 | Linear. One call per request, roughly 1,800 in and 200 out tokens. |
| SES | $0.30 | Linear. About three messages per request: ask, order, receipt. |
| DynamoDB | $0.19 | Linear, on-demand. A handful of writes and reads per request. |
| S3 | $0.12 | Grows with retained attachments, not with request rate. |
| Lambda | $0.08 | Linear. Six short invocations per request, all well inside 512 MB. |
| SQS | $0.04 | Linear, and effectively free below a million messages. |
| CloudWatch | $0.16 | Flat, if you set retention. Unbounded if you do not. |
| Secrets Manager | $0.40 | Flat. One secret, $0.40 a month. |
| AWS Budgets | $0.46 | Flat. Two budget actions, so you find out before the bill does. |
The Bedrock line assumes one read per request against a small, fast model — the cheapest one that can reliably turn a sentence into five fields, which is not a frontier model. Part 7 names the exact model id. Swapping it for something larger is the single fastest way to multiply this bill by ten for no measurable gain, because the task is extraction, not reasoning.
The three ways this bill surprises you
Every one of these has happened to somebody, and all three are cheap to prevent.
- A retry loop on the read. A malformed attachment makes the read throw, the function retries, the retry throws, and the queue redelivers. At three retries and no dead-letter queue that is one bad email costing you the same as a hundred good ones, every few minutes, until somebody notices. The fix is the dead-letter queue in Part 5 and a maximum receive count of three.
- Attachments nobody expires. Quote PDFs are small, and small times forever is not small. An S3 lifecycle rule that moves objects to Infrequent Access at 90 days and expires them at seven years — or whatever your record-keeping obligation actually is — keeps the storage line flat.
- Log retention left at never. CloudWatch defaults to keeping log groups forever. On a system this small the logs will eventually cost more than the compute. Thirty days of retention on every log group is a one-line change and the single highest-return cost setting in the whole design.
What it costs when nothing happens
This matters more than the headline number for a seasonal business. In a month with zero purchase requests, the bill is the fixed band: Secrets Manager at forty cents, AWS Budgets at forty-six, and a few cents of storage. Call it a dollar. There is no instance to stop, no cluster to scale down, and nothing to remember to turn off.
- Management
- Analytics
- Front-end & mobile
Set these on day one
- A dead-letter queue on every SQS queue, with a maximum receive count of three.
- Thirty-day retention on every CloudWatch log group. There is no default that is safe.
- An S3 lifecycle rule on the attachment prefix, tiering at 90 days and expiring at your actual record-keeping horizon.
- Two AWS Budgets actions — one that emails at half your expected spend, one that emails at double it. The second one is how you find out about a loop in an hour instead of a month.
- Provisioned concurrency: none. Nothing here is latency-sensitive enough to justify paying for a warm function.
Next: the same system drawn for engineers — service names, resource identifiers, IAM scopes, table schemas and the model id.
All posts