Series · 7 parts Published June 11, 2026

Form intake router

A serverless router that catches every form your website posts — contact, quote request, booking, signup; checks the fields, filters obvious spam, files each submission safely, and sends it to the right team and the right tool. If a downstream tool is down it retries and never drops the lead, and the customer always gets a “we got it” reply. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.

  1. 01

    A form intake router on AWS for a few dollars a month

    The whole system on one page — an intake door, a checker, and a dispatch piece, plus the moves they share for every submission so no lead is ever lost.

  2. 02

    How a form submission gets captured

    A tiny snippet posts the form to a Function URL; the door saves the raw payload, writes a record, and acknowledges the customer before any slow downstream work begins.

  3. 03

    How a form submission gets checked

    Required fields, format checks, and a layered spam filter that favors keeping a real lead. Plain Python on the hot path; one cheap model second-opinion only on borderline cases.

  4. 04

    How a form submission finds the right tool

    A routing table in a Drive sheet maps each form to a team email, a CRM list or sheet tab, and an auto-reply. Each delivery runs from a queue with retries so a busy tool never loses a lead.

  5. 05

    How a form submission gets confirmed

    The customer’s we-got-it reply, the de-duplicate guard against double-clicks, the retry budget, and the dead-letter queue that catches anything a downstream tool refuses — all logged.

  6. 06

    What the form intake router costs

    A couple of dollars a month at SMB volume. The hot path is plain Python and a couple of emails; Bedrock fires only on the few submissions that need a category guess or a spam second-opinion.

  7. 07

    Engineering reference: the form intake router architecture

    Same system, drawn purely for engineers. Service names, resource identifiers, region, Bedrock model IDs, Lambda inventory, IAM scopes, the SQS and DLQ config, and the DynamoDB schemas.

What is a form intake router?
A small serverless system that sits behind every form on your website — contact, quote request, booking, newsletter signup. Each form posts to it. It checks the fields are filled in correctly, filters obvious spam, saves the submission safely, and routes each one to the right place: it emails the right team, adds a row to your CRM or sheet, and sends the customer a “we got it” reply. If a downstream tool is briefly down, it retries and never drops the lead.
How much does it cost to run?
About $2/month at typical small-business volume (around 500 submissions a month). The fixed cost is essentially zero. The variable cost is dominated by the small amount of Lambda time per submission and the emails sent through SES; Bedrock fires only on the few submissions that need a category guess or a spam second-opinion, so it stays a small sliver. At 5,000 submissions a month the bill lands around $9.
Which AWS services does it use?
Lambda (Python 3.14, arm64) behind a Function URL that receives the form post, SQS with a dead-letter queue so a busy downstream tool never loses a submission, DynamoDB on-demand for the record and the de-duplicate check, S3 (with versioning) for the raw payload, SES outbound for the team email and the customer reply, Secrets Manager and Parameter Store for config, CloudWatch Logs (7-day retention), AWS Budgets, and Bedrock (Claude Haiku 4.5 via Global cross-Region inference) only for the category guess and a spam second-opinion. No API Gateway, no NAT Gateway, no always-on compute.
Where do submissions go after they are checked?
To wherever a routing table in a Google Sheet says they should. One row per rule: which form, which team email, which CRM list or sheet tab, and which auto-reply template. A small sheet-sync Lambda mirrors the sheet to S3 every 15 minutes; the router reads from S3 so a non-technical owner can change where a form goes without a deploy.
Does the router use AI?
Sparingly. The hot path is plain Python — it checks required fields, runs the spam rules, and looks up the routing rule by deterministic match. Bedrock Haiku 4.5 fires only when the routing table can’t decide a category from the fields alone (it reads the message text and proposes a category) and as a cheap second-opinion on a submission the spam rules marked as borderline. Most submissions never touch a model.
What happens if a downstream tool is down?
The submission is already saved and acknowledged before any downstream call is attempted, so the customer always gets a we-got-it reply. Each delivery (email the team, write to the CRM, write to the sheet) runs from SQS with automatic retries and backoff. If a tool stays down past the retry budget, the message lands in a dead-letter queue and an alert goes out; nothing is dropped, and the delivery is replayed once the tool recovers.
How does it stop spam without losing real leads?
A layered check that favors keeping a real lead over blocking a junk one. First, deterministic rules: a honeypot field, a minimum time-on-page, rate limits per IP, and a banned-pattern list from the rules doc. Borderline cases get one cheap Bedrock second-opinion. Anything flagged is filed in a held bucket — not deleted — so a human can release a false positive in one tap. A real lead is never silently thrown away.
All posts