Series · 7 parts Published May 8, 2026

Invoice chaser

A serverless chaser that watches which invoices are unpaid and past due; sends a polite reminder sequence to the right contact at the right cadence; escalates to the account owner when an invoice goes seriously late; and stops the moment payment lands. A human stays in control — nothing rude or wrong ever goes out. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.

  1. 01

    An invoice chaser on AWS for a few dollars a month

    The whole system on one page — an invoice intake, a chaser, and a sending piece, plus the four moves they share for every open invoice.

  2. 02

    How an invoice gets loaded

    Three lanes feed the invoice list — the Drive sheet exported from your accounting tool, an inbox-forwarding lane that parses invoice PDFs into proposed rows for one-tap approval, and a webhook lane that picks up new invoices the moment they are issued.

  3. 03

    How overdue gets detected

    A daily tick reads the invoice list, computes days-past-due per invoice, compares against per-terms cadences in the rules doc, and picks one of four moves: current, first nudge, follow-up, escalate. No model on the tick.

  4. 04

    How a reminder reaches the customer

    Contact resolution per invoice, quiet hours, weekends, a friendly-to-firm tone ladder, a pay-link in every reminder, and the four guardrails between the chaser’s chosen move and the actual email landing.

  5. 05

    How a chase stops on payment

    The chase stops the moment payment lands. Plus three owner actions: pause (hold without dismissing, capped per chain), mark disputed (stop chasing, flag for a human), and write off (close it out). Every action is logged.

  6. 06

    What the invoice chaser costs

    A couple of dollars a month at SMB volume. The chaser runs once a day, calls no models on the tick, and only fires Bedrock on the inbound parsing lane and the monthly summary.

  7. 07

    Engineering reference: the invoice chaser architecture

    Same system, drawn purely for engineers. Service names, resource identifiers, region, Bedrock model IDs, Lambda inventory, IAM scopes, the SES inbound rule set, EventBridge Scheduler config, and the DynamoDB schemas.

What is an invoice chaser?
A small serverless system that watches which invoices are unpaid and past due; sends a polite reminder sequence to the right contact at the right cadence; escalates to the account owner when an invoice goes seriously late; and stops the moment payment lands. The owner can pause a chase, mark an invoice as disputed, or write it off directly from the daily review.
How much does it cost to run?
About $2.40/month at typical small-business volume (around 200 open invoices). The fixed cost is essentially zero. The variable cost is dominated by the daily Lambda tick that reads every open invoice; Bedrock and Textract fire only on the inbound parsing lane and the monthly summary, so they’re small slivers. At 2,000 open invoices the bill lands around $13.
Which AWS services does it use?
Lambda (Python 3.14, arm64) with Function URLs for the pay-link and approve endpoints, EventBridge Scheduler for the daily tick and deferred-send one-offs, DynamoDB on-demand, S3 (with versioning), SES inbound + outbound, Secrets Manager, CloudWatch Logs (7-day retention), AWS Budgets, and Bedrock (Claude Haiku 4.5 via Global cross-Region inference) for the inbound parsing and monthly summary. No API Gateway, no NAT Gateway, no always-on compute, no Knowledge Base.
Where does the invoice list live?
In a Google Sheet in a Drive folder, exported from your accounting tool. One row per invoice with number, customer, contact email, amount, issue date, due date, terms, and a link to the invoice PDF. A small drive-sync Lambda mirrors the sheet to S3 every 15 minutes; the chaser reads from S3 to keep Drive API calls predictable and to get S3 versioning for free.
Does the chaser use AI?
Sparingly. The daily tick uses no AI — it’s plain Python that reads dates and decides on a move. Bedrock Haiku 4.5 fires only when somebody forwards an invoice PDF (Textract + Haiku propose a row for human approval) and once a month for the cash-flow summary. Most of the system is deterministic by design.
How does a reminder stay polite and not annoying?
Each set of terms has its own cadence in the rules doc — net-30 gets a gentle nudge at 3 days late, a firmer follow-up at 10, and an escalation at 21. The reminders climb a tone ladder from friendly to firm; nothing rude ever goes out. Sends respect quiet hours and weekends. A paused or disputed invoice stops chasing entirely. And every chase stops the moment payment lands.
What happens when an invoice is paid?
The chase stops on the next tick. The chaser watches the accounting feed and the paid column; when an invoice is marked paid, the live chain is cleared and a thank-you can go out. The owner can also pause a chase, mark disputed, or write off an invoice. Every action is recorded in the ic-audit DynamoDB table with timestamp, invoice, action, by-user, and a before-and-after snapshot, so the trail is auditable for years.
All posts