Skip to content

Part 1 of 7 · Consent preference keeper series ~6 min read

A consent preference keeper on AWS for a few dollars a month

Marketing consent goes wrong in small businesses in a specific and expensive way. There are four systems that can send something — the newsletter tool, the e-commerce platform, the booking system, somebody’s mail merge — and each holds its own opinion about who is subscribed. Somebody unsubscribes from one and keeps hearing from two others. This post walks through a small system that gives all four the same answer.

man in grey t-shirt smiling to woman at a counter
Photo by Clay Banks on Unsplash

Key takeaways

  • One authoritative record, and every sending system asks it rather than holding an opinion.
  • Every change is an immutable event with its evidence, not an updated flag.
  • Consent is per purpose. Agreeing to order updates is not agreeing to a newsletter.
  • A withdrawal takes effect immediately and is pushed to every downstream copy.
  • Designed on AWS for about $2 a month.

The whole system on one page

Before any code, here is the shape of what we are designing.

System: consent events recorded, resolved and propagatedThree boxes across the top sit outside the AWS account. On the left, Where consent happens: forms, checkout and unsubscribe links. In the middle, Sending systems: all of them, always asking. On the right, Whoever is asked the question why did you email me. Each connects by an arrow to the AWS account container below. A consent event flows down into the account. Sending systems ask whether they may send. The evidence goes back out. Inside the AWS account are three components in a row. On the left, the Event log, immutable and holding the evidence. In the middle, the Resolver, answering one question: may we send this. On the right, the Propagator, which pushes withdrawals and verifies them. A note at the bottom says it cannot intercept a send, so every sending system has to ask, and unreachable means no.AWS ACCOUNTWhere consent happensforms, checkout,unsubscribe linksSending systemsall of them, always askingWhoever is asked'why did you email me?'Event logimmutable, withthe evidenceResolverone question:may we send this?Propagatorpush withdrawals,and verify thema consent eventmay we send?the evidenceIt cannot intercept a send. Every sending system has to ask, and unreachable means no.
Fig 1. Three things outside the account, three pieces inside it. The system is advisory by construction, which makes the discipline in the sending systems the load-bearing part.
  • App integration
  • Management
  • Analytics
  • Front-end & mobile
  • People

Events, not a flag

A boolean on a customer record answers what is true now and destroys everything about how it became true. That is fine until somebody asks why they received an email, which in this domain is not a support question but a regulatory one, and the answer has to be specific: on this date, through this form, with this wording, they agreed to this.

So every change is an append-only event carrying its evidence: the source, the exact wording shown, the page, the timestamp and whatever identifier proves it was them. The current state is computed from the events rather than stored, which means the two can never disagree.

What runs (the inside)

  • The event log. Append-only, one row per consent or withdrawal, with the evidence attached. Part 2 covers what evidence has to be captured for it to be worth anything.
  • The resolver. Answers one question — may we send this purpose to this person — from the events, with a heavy cache because it is asked constantly. Part 3.
  • The propagator. A withdrawal is only real when every system that could send knows about it. Part 4 is about pushing that out and, more importantly, verifying it arrived.

One withdrawal, end to end

One consent withdrawal from click to verified suppression, in five stagesA horizontal row of five boxes joined by arrows. Unsubscribe clicked: in one email. Event recorded: with the evidence. State recomputed: immediately. Pushed: to four systems. Verified: all four confirmed. A note says the fifth box is the one that is usually missing and it is where the failures are.ONE WITHDRAWAL, END TO ENDUnsubscribe clickedin one emailEvent recordedwith the evidenceState recomputedimmediatelyPushedto four systemsVerifiedall four confirmedThe fifth box is the one that is usually missing, and it is where the failures are.
Fig 2. The same system as one line. Verification of the push is the step most implementations omit, and a silently failed suppression is exactly the failure that produces a complaint.
  • Machine learning
  • Networking
  • Management
  • Analytics

In plain words

Somebody clicks unsubscribe in a newsletter. The link records a withdrawal event for the marketing purpose, with the campaign it came from, the timestamp and the signed token that proves it was that recipient. Their state for marketing becomes withdrawn immediately.

The propagator then pushes that to the four systems that hold their own lists: the newsletter tool, the e-commerce platform, the booking system and the CRM. Three confirm within seconds. The fourth — the booking system, whose API is slow — is retried and confirms four minutes later. All four are recorded as confirmed with timestamps.

Fourteen months later that person emails asking why they were contacted about a special offer. The answer takes about ten seconds to produce: they withdrew from marketing on the 7th of August 2026, the send in question was an order-related notification under a different purpose they have not withdrawn from, and here is the exact wording they agreed to when they placed the order. That is a completely different conversation from the one that starts with somebody checking a flag.

Design rules that shaped every decision

  • Events, never a flag. The current state is computed and the history is the point.
  • Consent is per purpose. Order updates, marketing and service messages are different questions.
  • Never infer consent. A purchase is not agreement to a newsletter, however convenient that would be.
  • Withdrawal is immediate and pushed, and the push is verified rather than assumed.
  • Unreachable means do not send. A resolver that is down must fail closed.
  • The evidence is captured at the moment, not reconstructed later. Wording changes.

Why this shape

Consent management platforms exist and are good, and for a business of any size they are usually the right answer. The reason to build a small one is that most small businesses will not buy one and will instead keep four independent lists, which produces the specific failure this system exists to prevent: somebody unsubscribing and still hearing from you.

So the design is deliberately small enough to actually get built: one table of events, one question, and a push. It does not manage cookie consent, it does not produce a compliance dashboard, and it does not try to be a customer data platform. It answers one question consistently and keeps the evidence.

The next four posts walk through each piece: how an event is recorded, how the answer is resolved, how a withdrawal propagates, and what the evidence has to look like. One diagram per post, a cost breakdown, and an engineering reference at the end.

All posts