Skip to content

Part 6 of 7 · Purchase order approver series ~5 min read

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.

Monthly cost of the purchase order approver at three request volumesA stacked bar chart with three bars. The left bar represents eighty purchase requests a month and totals about one dollar ninety. The middle bar represents two hundred requests and totals about three dollars thirty. The right bar represents one thousand requests and totals about eleven dollars fifty. Each bar is stacked from five bands. The largest and fastest-growing is Bedrock, one read per request, shown in teal. Below it, SES for the asks, orders and receipts, in pink. Then S3 and DynamoDB storage in green. Then a fixed band in orange for Secrets Manager and AWS Budgets, which is eighty-six cents at every volume. Then a grey band for Lambda, SQS and CloudWatch. A note says the read is the only bar that grows with the business and the orange band never moves.$0$5$10$15$20~$2.0480 requests~$3.3200 requests~$11.51,000 requestsBedrock -- one read per requestSES -- asks, orders, receiptsS3 + DynamoDBFixed -- Secrets Manager, BudgetsLambda, SQS, CloudWatchThe read is the only bar that grows with the business. The orange band never moves.
Fig 1. The monthly bill at three volumes. The teal band — one model read per request — is the only part that grows; the orange fixed band is the same 86 cents whether you make eighty requests or a thousand.

Line by line

LineAt 200 requestsHow it scales
Bedrock read$1.55Linear. One call per request, roughly 1,800 in and 200 out tokens.
SES$0.30Linear. About three messages per request: ask, order, receipt.
DynamoDB$0.19Linear, on-demand. A handful of writes and reads per request.
S3$0.12Grows with retained attachments, not with request rate.
Lambda$0.08Linear. Six short invocations per request, all well inside 512 MB.
SQS$0.04Linear, and effectively free below a million messages.
CloudWatch$0.16Flat, if you set retention. Unbounded if you do not.
Secrets Manager$0.40Flat. One secret, $0.40 a month.
AWS Budgets$0.46Flat. 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.

The monthly bill at four request volumes plus one failure modeA horizontal row of five boxes. Quiet month, about one dollar. Eighty requests, about two dollars. Two hundred requests, about three dollars. One thousand requests, about twelve dollars. And one bad retry loop, about two hundred dollars. A note says four of these are the design working and the fifth is a missing dead-letter queue.THE BILL, AT A GLANCEQuiet month~$180 requests~$2200 requests~$31,000 requests~$12One bad loop~$200Four of these are the design working. The fifth is a missing dead-letter queue.
Fig 2. The bill at a glance, including the one that is not a volume at all. A retry loop with no dead-letter queue costs more than every legitimate use of the system put together.
  • 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