What the expense approver costs
The approver is one of the cheaper systems in this whole series. The expensive-sounding part — reading a photo of a receipt — is a few tenths of a cent per claim. The policy check that decides each claim’s fate is plain Python and costs almost nothing. Bedrock fires once per claim to sort the category and once a month for a board summary. At typical SMB volume, the bill is a couple of dollars a month, fixed cost essentially zero.
Key takeaways
- Around $2.40/month at typical SMB volume (around 200 claims a month).
- Fixed AWS cost is essentially zero. No always-on compute, no NAT Gateway, no API Gateway.
- The policy check costs pennies — no model calls on the decision.
- Textract reading each receipt is the dominant cost; the category sort is a small Bedrock sliver.
- At 1,000 claims a month the bill is around $11. At 1,800 it’s around $19.
Cost at three volumes
Where the dollars actually go
Textract (the bulk). Each claim has one receipt, and Textract reads it once. Receipt reading runs a few tenths of a cent per page, and most receipts are one page. At 200 claims that’s around a dollar; at 1,800 it’s a handful of dollars. This is the single largest line, and it’s still small — reading a receipt by machine is cheap, and it only happens once per claim.
Bedrock (the category sort). One small Haiku 4.5 call per claim reads the receipt text and picks a category. A few hundred input tokens and a handful of output tokens, so a fraction of a cent each. The monthly summary is one larger call: a board-ready paragraph on the month’s spend by category. Bedrock lands at cents to a couple of dollars across these volumes.
Lambda runtime. The intake Lambda, the checker, the routing Lambda, and the decision handler each run for a fraction of a second per claim. At any of these volumes the Lambda total is well under a dollar.
DynamoDB on-demand. Two small tables: ea-claims and ea-audit. A few reads and writes per claim. Pennies a month at any of these volumes.
S3 + storage. The receipt images plus the raw MIME from any forwarded receipts. A few megabytes a month at SMB volume. Effectively free, and lifecycle rules push old receipts to cheaper storage.
SES. Inbound for the forwarding lane and outbound for email-fallback approvals and claimant notices: $0.10 per thousand messages either way. A few cents a month at this scale.
EventBridge. Routing claim events plus the deferred one-offs from the quiet-hours gate. A few events per claim. Pennies.
What doesn’t cost money
- API Gateway. Replaced by Lambda Function URLs for the submit form and the approve buttons.
- NAT Gateway. Nothing is in a VPC. No NAT, no $32/month minimum.
- Always-on compute. No EC2, no Fargate. Every Lambda sleeps until a claim or a decision wakes it.
- A Knowledge Base. The policy is short structured rules, not free text — deterministic lookup beats vector search here. No embeddings, no Knowledge Base, no S3 Vectors needed.
- A model on the policy check. The decision is plain Python comparing an amount to a limit. Bedrock fires only on the category sort and the monthly summary.
How the cost scales
Textract and Bedrock grow linearly with claim count, because each claim has one receipt to read and one category to sort. Lambda and DynamoDB grow linearly too but stay tiny. So the bill at 5,000 claims a month is around $50; at 10,000 it’s around $100. Past those volumes you’re a bigger business than this design targets, and you’d look at batching Textract or caching common-vendor categories — but those are optimizations, not redesigns.
Set an AWS Budgets alarm at $25/month so anything unusual pages you before the bill matters. The approver’s normal-volume bill stays well under that ceiling.
Last post in the series: the engineering reference. Same system, drawn for engineers — service names, Lambda inventory, IAM scopes, DynamoDB schemas, the Textract flow, and EventBridge config.
All posts