Upsell recommender
Most add-on sales are lost in the same quiet way: the customer buys the bike and never hears that the shop also stocks the lights and the lock that go with it. This is the design of a small serverless system that turns a placed order into one tasteful, well-judged nudge: it reads what was bought and the customer’s history, asks a model to propose a shortlist of add-ons, and then lets deterministic catalogue rules decide — in stock, genuinely complementary, sensibly priced, not already owned. It sends one follow-up with a one-tap add link, tracks whether the add-on was taken up so the offer can be measured, and caps how often anyone is nudged so it never feels like spam. One suggestion per order, opt-out honoured, and no offer at all when nothing fits. Seven posts on the same system — one diagram at a time — with an engineering reference at the end.
-
01
An upsell recommender on AWS for a few dollars a month
The whole system on one page — the order webhook, the pick where a model proposes and catalogue rules dispose, a one-tap add link, and take-up tracking, plus the guardrail that it sends one offer per order, caps how often anyone is nudged, and says nothing when nothing fits.
-
02
How an order triggers a suggestion
How a placed order becomes a candidate for a suggestion — the store webhook, signature checks, one-order-one-offer dedup, the opt-out and per-customer frequency-cap gate, and gathering what was bought and the customer’s history before anything is picked.
-
03
How the add-ons get picked
How the add-on gets chosen — the single Bedrock call that proposes a ranked shortlist, and the deterministic catalogue rules that dispose of it: in stock, genuinely complementary, sensibly priced, not already owned. The top survivor wins, and if the shortlist empties, no offer is sent.
-
04
How the offer gets sent
How the offer reaches the customer — the short, deliberate delay before sending, the one nudge composed from the chosen add-on, and the one-tap add link: a signed token on a Lambda Function URL that records the tap and redirects straight into the store’s add-to-cart.
-
05
How a take-up gets tracked
How a take-up gets measured — the one-tap link recording the tap inside an attribution window, the per-customer frequency cap that keeps the next nudge honest, and the scheduled sweep that closes the window so every offer ends up counted as taken, ignored, or never sent.
-
06
What the upsell recommender costs
A line-by-line monthly cost at about $2.60 for roughly 150 orders, where the money actually goes (one Bedrock call per order is the biggest line here, then the nudge), and what the bill looks like at ten times the volume.
-
07
Engineering reference: the upsell recommender architecture
The same system drawn for engineers — the Lambda inventory, the two Function URLs, the EventBridge send and sweep, DynamoDB tables and key schema, how the pick stays idempotent, SNS and SES, IAM scope, the Bedrock model id, and the region.
Frequently asked questions
- What is an upsell recommender?
- It is a small serverless system that watches for placed orders and, just after one lands, sends the customer a single well-judged nudge for the one add-on that actually goes with what they bought. When the store fires an order webhook, the system reads the basket and the customer’s history, asks Bedrock to propose a shortlist of complementary products, and then lets deterministic catalogue rules pick the winner — in stock, complementary, sensibly priced, not already owned. The customer gets one follow-up with a one-tap add link, and if nothing genuinely fits, nothing is sent at all.
- How much does it cost to run?
- About $2.60/month at a typical small-shop volume of roughly 150 orders a month. There is no always-on compute, so the bill is almost entirely usage-priced — the one Bedrock call per order is the largest line here because the model reads the basket and a candidate list every time, followed by the outbound nudge, with Secrets Manager the only real fixed cost. At ten times the volume (around 1,500 orders a month) the bill lands near $17, because the fixed lines don’t move and only the model call and the nudge scale.
- Which AWS services does it use?
- Lambda (Python 3.14, arm64) behind two Function URLs — one for the order webhook and one for the one-tap add-link redirect — DynamoDB on-demand for orders, offers, a catalogue mirror, customers and an opt-out list, EventBridge Scheduler for the delayed send and the take-up-window sweep, SNS for the outbound SMS nudge and SES for the internal take-up report, SQS with a dead-letter queue, Secrets Manager for the store and signing keys, CloudWatch Logs with 7-day retention, AWS Budgets, and Bedrock (Claude Haiku 4.5 via Global cross-Region inference) to propose and phrase the offer. No API Gateway, no NAT Gateway, no always-on compute. One region,
eu-west-2. - When does the nudge go out?
- A short, deliberate delay after the order confirms — long enough not to interrupt the checkout glow, soon enough that the add-on is still relevant. The webhook records the order and gathers context within seconds; the pick runs once, and a scheduled send releases the nudge after the configured delay (an hour or so by default, tunable per shop). If the customer has been nudged too recently, or has opted out, or nothing in the catalogue genuinely fits, the send never happens — the system would rather say nothing than send a weak offer.
- Does it use AI to decide what to sell?
- No — it uses AI only to propose and phrase. Bedrock’s Claude Haiku 4.5 fires once per order to suggest a ranked shortlist of add-ons and a short line for each, but every real decision is deterministic Python: the trigger, the dedup, the opt-out and frequency-cap checks, and above all the catalogue rules that filter the model’s shortlist down to something in stock, complementary, sensibly priced and not already owned. The model proposes; Python disposes. A suggestion the model likes but the rules reject never reaches the customer.
- Can it nag people or push things that are out of stock?
- No. A per-customer frequency cap means nobody is nudged more than once in a set window, so a regular who orders weekly still only hears from it occasionally, and an opt-out is permanent. The catalogue rules are a hard filter run after the model proposes: anything out of stock, already owned, wrongly priced, or not genuinely complementary is dropped, and if the shortlist empties, no offer is sent. It suggests exactly one add-on per order, only ever one, and stays silent whenever a good suggestion isn’t available.