How a cart reminder reaches the shopper
The waiter picked a move — first reminder or second reminder. Now the sender has to figure out who to email, whether now is a decent time of day, whether this shopper has had enough already, and what the message should actually say. Get any of those wrong and the reminder is worse than none at all: a 3am ping, a second email to someone who unsubscribed, a generic blast that reads like spam. Four small guardrails sit between the move and the actual email.
Key takeaways
- Address resolution: a cart with no email can’t be reminded — it’s skipped, not guessed.
- Quiet hours defer the send to the next decent hour instead of pinging overnight.
- A do-not-disturb check skips anyone who unsubscribed or got a reminder very recently.
- Bedrock Haiku 4.5 polishes one line into your store’s voice, with a plain fallback if it’s down.
- Every email carries the items, a return link, and a one-click unsubscribe; every send is logged.
Four guardrails on every send
Gate 1: resolve the address
The sender needs an email to send to, and the only honest source is the cart row itself. If the shopper entered their email at checkout before leaving, it’s on the row and the sender uses it. If they never reached the email field — an anonymous cart — there’s nothing to send to, and the cart is simply skipped. The system never buys, guesses, or matches an address from somewhere else. A reminder is only worth sending to someone who actually handed you their email; anything else is the kind of guessing that erodes trust fast.
Carts with an email but no name still get a warm, generic greeting (“Hi there”). The copy never pretends to know more about the shopper than the cart actually told you.
Gate 2: quiet hours
A cart abandoned at 11pm shouldn’t produce an email at 11pm, even if the wait technically elapsed. Gate 2 reads the rules doc’s quiet-hours setting (default 9pm to 8am, in the shopper’s timezone where known, otherwise the store’s). If the current local time is inside the quiet window, the sender creates a one-off EventBridge Scheduler rule that fires at the next decent minute and exits without sending. The Scheduler re-invokes the same sender with the same payload at the deferred time, where Gate 2 will let it through.
This is also why the waits in Part 3 are deliberately not razor-thin — a small buffer means the quiet-hours defer rarely has to push a send more than a few hours, so a cart abandoned late at night still gets its reminder first thing in the morning rather than days later.
Gate 3: do not disturb
Two things can make a send unwelcome even when the timing is fine. First, the shopper may have unsubscribed — from this cart, or from all reminders. Gate 3 checks the unsubscribe list and skips anyone on it, no exceptions. Second, the same person may have abandoned several carts in a short span; sending three reminders in two days, even for different carts, feels like a barrage. So Gate 3 also skips a send if that email got any reminder in the last few days (the window is configurable in the rules doc).
This gate is what turns “one reminder per cart” into “one gentle nudge per shopper.” The promise on the box — never pushy, one nudge not a barrage — lives mostly here.
Gate 4: compose, polish one line, then ship
The voice doc has one email template per move: a short, warm message with placeholders for the greeting, the items, the cart total, the return link, and the unsubscribe link. The sender fills the placeholders, then makes exactly one Bedrock Haiku 4.5 call — to rewrite just the opening line into your store’s voice, given the items and whether the cart was a saved-link cart. The model gets a tight prompt and a one-sentence budget; if it’s slow or unavailable, the sender falls back to the plain template line and ships anyway. The AI never touches the items, the total, the link, or the unsubscribe — only the tone of one sentence.
The composed email goes out via SES SendRawEmail, with a proper List-Unsubscribe header so the shopper’s mail client shows a one-click opt-out at the top, and a visible unsubscribe link in the footer that hits a Function URL. Both record the opt-out the same way. A second reminder uses the slightly warmer template and gently references that the cart’s still saved — never that “you ignored our last email.”
Every send — first or second — writes a row to cr-sends in DynamoDB. The next wake-up reads that row and knows not to send the same reminder again.
Why the guardrails exist
None of these gates are exotic. They’re the kind of small care a thoughtful shopkeeper would take if they were emailing each shopper by hand — only write to someone who gave you their address, don’t email at midnight, leave alone anyone who asked to be left alone or who you just wrote to, and say something warm and specific rather than a form blast. Putting them in code as four small sequential gates makes them part of the design, not something you’re trusting one email template to remember.
Next post: how a cart recovery stops the moment the shopper checks out — and the three ways a human can stop it by hand.
All posts