Refund handler
A serverless handler that reads each refund request, checks it against your own written refund policy, drafts a clear and kind reply, and routes the easy ones for one-tap approval — while sending anything out of policy or high-value straight to a human. It never issues money on its own; a person approves every refund. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.
-
01
A refund handler on AWS for a few dollars a month
The whole system on one page — an intake, a checker, and a reply piece, plus the one rule they all share: a person approves every refund.
-
02
How a refund request arrives
Three lanes feed one queue — a help inbox that catches forwarded emails, a contact-form webhook, and a manual paste lane for requests that came in by phone or chat.
-
03
How a refund gets checked against policy
The checker pulls the exact policy lines that apply, decides only from them, and picks one of four outcomes: in policy, out of policy, high-value, or not covered. It only acts on what the policy says.
-
04
How a refund reply gets drafted
The drafter writes a kind, plain reply in your voice, quotes the policy line it used, and four guardrails sit between the draft and the person who approves it.
-
05
How a refund gets approved
Two actions on the approval card: approve (send the draft as-is) and edit (change it first). A third path declines with a reason. The money only moves after a human taps. Every action is logged.
-
06
What the refund handler costs
A few dollars a month at SMB volume. The handler runs only when a request comes in, calls cheap models for most cases, and reserves the heavier model for the few hard ones.
-
07
Engineering reference: the refund handler architecture
Same system, drawn purely for engineers. Service names, resource identifiers, region, Bedrock model IDs, the S3 Vectors index, Lambda inventory, IAM scopes, the SES inbound rule set, and the DynamoDB schemas.
Frequently asked questions
- What is a refund handler?
- A small serverless system that reads each refund request, checks it against your own written refund policy, drafts a clear and kind reply, and routes the easy ones for one-tap approval while sending anything outside policy or high-value straight to a human. It never issues money on its own; a person approves every refund before any reply goes out.
- How much does it cost to run?
- About $3/month at typical small-business volume (around 200 requests a month). The fixed cost is essentially zero. Most of the variable cost is the model calls that read the request and draft the reply; the policy index is tiny and the traffic is small. At 2,000 requests a month the bill lands around $14.
- Which AWS services does it use?
- Lambda (Python 3.14, arm64) with Function URLs for the form webhook and the approve button, DynamoDB on-demand, S3 (with versioning), SES inbound + outbound, SQS with a dead-letter queue, Secrets Manager, CloudWatch Logs (7-day retention), AWS Budgets, and Bedrock (Claude Haiku 4.5 for reading and drafting, Claude Sonnet 4.6 only for the few hard cases) via Global cross-Region inference. The policy is indexed with Titan Text Embeddings V2 into Amazon S3 Vectors. No API Gateway, no NAT Gateway, no always-on compute.
- Where does the refund policy live?
- In a Google Doc in a Drive folder. You write the policy in plain prose — windows, conditions, exceptions, dollar caps. A small
policy-syncLambda mirrors the doc to S3 every 15 minutes and re-indexes it into S3 Vectors so the checker always reads the current policy. Change a rule in the doc and the next request uses it; no deploy. - Does it ever send money by itself?
- No. The handler reads, checks, and drafts — it never issues a refund or sends a reply on its own. Every refund waits on a human tap. In-policy, low-value cases get a one-tap approve card with the draft attached; out-of-policy or high-value cases skip the easy lane and go straight to a person with the policy citation and the reason. The money only moves after someone approves.
- How does it stay grounded in our actual policy?
- Every check pulls the exact policy passages that apply to the request and feeds them to the model with a strict instruction: decide only from these passages, cite the line you used, and if nothing covers the case say so. The draft reply quotes the same policy line. If the request isn’t covered by any passage, it’s marked not-covered and routed to a human instead of guessed at.
- What happens when I approve a refund?
- Two buttons on every card: Approve sends the drafted reply as-is and records the decision; Edit opens the draft in a box to change before sending. On approve, the reply goes out via SES, the request is marked resolved, and the action is recorded in the
rf-auditDynamoDB table with timestamp, request id, decision, by-user, the policy line cited, and the dollar amount — so every refund is auditable for years.