Series · 7 parts Published June 23, 2026

Lead enricher

A serverless enricher that catches every raw inbound lead the moment it arrives, cleans the messy fields, fills in the company from the email domain, checks it against your CRM so the same person doesn’t land twice, and quietly drops the obvious junk — all before anything is written. It does not score leads and it does not route them; it cleans and completes them, then hands a tidy record to the CRM. Designed on AWS for about $2.50/month at typical small-business volume. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.

  1. 01

    A lead enricher on AWS for a few dollars a month

    The whole system on one page — intake, normalise, enrich, dedupe, and a junk filter in front of the CRM — and the one rule that shapes it: clean and complete, never score or route, never overwrite.

  2. 02

    How a raw lead gets normalized

    A deterministic normaliser fixes name casing, formats the phone to E.164 and the email to a canonical form, and resolves the country — with one small Bedrock call only for the genuinely ambiguous bits.

  3. 03

    How a lead gets enriched

    From a clean email domain, a firmographic lookup adds the company, its size, industry, and location — with the API key in Secrets Manager, the result cached, and every field traceable back to its source.

  4. 04

    How a duplicate gets caught

    An identity index mirrors the CRM on normalised keys; an exact-key check catches obvious repeats and a fuzzy pass catches the rest, with Bedrock judging only the genuinely ambiguous near-matches.

  5. 05

    How junk gets filtered out

    A layered junk filter — cheap deterministic checks first, a bounded model judgement only for the borderline cases — drops obvious spam before anything is written, and logs every drop so nothing vanishes silently.

  6. 06

    What the lead enricher costs

    A line-by-line cost breakdown at about 1,000 leads a month summing to roughly $2.50, where the enrichment API is the main variable, plus what changes at 10× the volume.

  7. 07

    Engineering reference: the lead enricher architecture

    The same system drawn for engineers: the Lambda inventory, the schedules, the DynamoDB dedupe index and its key schema, the S3 and SES setup, IAM scoping, the Bedrock model id, and the region.

What is a lead enricher?
A small serverless system that sits in front of your CRM. When a raw lead arrives from a form or webhook with messy, partial fields, the enricher normalises it (name casing, phone and email format, country), enriches it from public firmographic data (company from the email domain, plus size, industry, and location), dedupes it against the people already in your CRM using fuzzy matching so the same person doesn’t land twice, and filters obvious junk and spam before anything is written. Clean, completed records go to the CRM; junk is logged and dropped. It is distinct from a lead-intake bot — it does not score leads or route them to a rep, it cleans and completes them.
How much does it cost to run?
About $2.50/month at typical small-business volume (around 1,000 leads a month). The fixed cost is essentially zero. The main variable cost is the firmographic enrichment API — roughly a dollar a month at that volume — followed by a small Bedrock Haiku 4.5 spend for the fuzzy normalisation and dedupe judgement. Lambda, DynamoDB, S3, SES, and SQS together come to pennies, and Secrets Manager is a flat 40 cents for the one stored API key. At 10× the volume (around 10,000 leads a month) the bill lands near $21, almost all of it the enrichment API and Bedrock; the fixed pieces barely move.
Which AWS services does it use?
Lambda (Python 3.14, arm64) for each pipeline stage, EventBridge Scheduler for retries and overnight backfill, DynamoDB on-demand for the dedupe/identity index, S3 for the raw payloads and the enriched records, SES for the daily junk digest and ops alerts, SQS with a dead-letter queue between stages, Secrets Manager for the enrichment API key, CloudWatch Logs at 7-day retention, and AWS Budgets for a cost alarm. Bedrock (Claude Haiku 4.5 via the Global cross-Region inference profile) is used sparingly for fuzzy normalisation and ambiguous dedupe judgement. No API Gateway, no NAT Gateway, no always-on compute, and everything runs in one region (eu-west-2).
How does it catch duplicates against the CRM?
It keeps a small DynamoDB identity index that mirrors the people already in your CRM, keyed on normalised signals — lowercased email, the E.164 phone number, and a name-plus-company fingerprint. A new lead is first checked for an exact match on those keys; if nothing exact is found, a fuzzy pass compares the normalised name, company, and domain, and only genuinely ambiguous cases are sent to Bedrock Haiku 4.5 for a same-person / different-person judgement. A confident match links the lead to the existing record rather than creating a second one; a confident non-match is written as new.
Does it use AI?
Sparingly, and never as the only thing standing between a lead and your CRM. The bulk of the work — case-fixing, phone and email formatting, exact-key dedupe, the junk checks — is plain deterministic Python. Bedrock Haiku 4.5 is called only where fuzzy judgement actually helps: splitting an awkward full name, inferring a country, or deciding whether a near-match is really the same person. Every model output is bounded by deterministic rules afterwards, so a model can never invent a field that isn’t supported by the input.
Can it overwrite or corrupt a CRM record on its own?
No. The enricher only ever creates a new clean record or links a lead to one that already exists; it does not overwrite the fields on an existing CRM contact. When it finds a confident duplicate it attaches the new enquiry to the existing person and adds any genuinely missing fields, but it never replaces a value a human already entered. Junk is dropped, not written. Every decision — normalised, enriched, matched, or dropped — is logged with the before-and-after so you can audit exactly what reached the CRM and why.
All posts