Case notes

Case note: a loyalty mechanic in five days, not five months

TL;DRWe shipped a returnables-aware double-points combo across every market in five days because the mechanic was configuration, not code: loyalty rules live in one service, empties events were already on the shared bus, and points liability is recomputed nightly. Each market went live behind its own flag. Enterprise loyalty builds usually run six to eighteen months.

The client wanted a returnables-aware promotion: double points on a case combo, but only when the empties came back. We shipped it across every market in five days, not the five-to-eighteen months an enterprise loyalty build typically runs, because the mechanic was configuration rather than code. Loyalty rules live in one service, empties events were already on the bus, and each market went live behind its own feature flag.

Why does an enterprise loyalty change usually take months?

Because in most stacks the loyalty engine is a separate system with its own data model, its own integrations and its own release calendar, so a new mechanic is a project rather than a setting. The published benchmarks are sobering. A 2026 buyer's guide puts enterprise loyalty implementations at six to eighteen months, driven by data migration, multi-system integration and change management. Even a deliberately narrow scope is not quick: an implementation partner describes a single-program Salesforce Loyalty rollout — one earn model, three tiers, basic redemption — as a twelve-to-sixteen-week engagement. Faster tiers exist, but the same guide still quotes a mid-market full-service programme at ninety to a hundred and twenty days.

Brewers get the worst of it, because the interesting mechanics are physical. "Double points on a case combo, but only when the empties come back" is not a loyalty rule in isolation; it spans loyalty, returnables, order capture and stock. In a stitched-together stack those are four systems owned by four vendors, and the combo becomes four change requests that all have to land in the same release. That is how a five-day idea turns into a two-quarter programme.

What made five days possible?

Three things, none of them clever on their own. First, loyalty rules are configuration in one service, versioned like any other config, so a new earn rule is an edit and a review, not a code deploy and a migration. Second, the empties events were already on the event bus — the same stream that carries orders and deliveries — so "did the empties come back for this outlet" was a fact we already held, not an integration we had to build. Third, we recompute the outstanding points liability nightly from the event log, so adding an earn rule does not require anyone to hand-model what it will cost.

The contrast is easiest to see step by step.

StepTypical loyalty stackOur stack
Define the mechanicCode change in the loyalty engine, scheduled into a releaseVersioned config edit in one service, peer-reviewed
Know the empties came backNew integration between returnables and loyaltyAlready an event on the shared bus
Cost the liabilityManual forecast, reconciled at quarter closeRecomputed nightly from the event log
Go live per marketCoordinated multi-system releaseFeature flag flipped per market
Undo a mistakeRoll back the release and hope nothing else movedTurn the flag off

This is the same discipline that let us take order capture off the ERP hot path: when the operational events already live on one bus, a new feature is mostly a matter of reading what is already there. Our architecture is one event bus precisely so that the returnables signal a loyalty rule needs is the same signal delivery and stock already consume — nobody builds a bespoke pipe to answer a question the bus already answers.

How did we keep the points liability honest?

A loyalty programme is a liability before it is a marketing win: every unredeemed point is deferred revenue that someone in finance has to carry, and a new double-points mechanic moves that number. The failure mode we have seen elsewhere is a loyalty engine that reports issued and redeemed points but leaves the outstanding liability to a spreadsheet reconciled at quarter close, so the finance team learns the true cost of a promotion a quarter after it ran. We recompute the outstanding liability nightly from the event log, so the morning after a mechanic goes live the number has already moved and finance can see by how much. That is the same reporting discipline that lets us answer a finance question the same afternoon instead of the next quarter — a liability you compute nightly is one you can actually defend in a review.

What didn't go to plan?

The technology was ready on day five. Going live was not, in two markets, and the reason was not ours to fix. Loyalty mechanics that reward buying more alcohol are regulated differently across markets: in some jurisdictions "buy the combo, earn double" reads as a promotional inducement and needs a compliance sign-off before it can run. Legal review is per market, and in two of them it took weeks longer than the build did. We were finished; the lawyers were not, and they were right to be careful.

What saved this from being a delay was the flag itself. "Deployed" and "enabled" were already two different states, so the mechanic sat dark in those two markets — shipped, tested, costed, switched off — until legal cleared it, at which point going live was one flag flip with no fresh release. The honest lesson is not that we were slow; it is that we had quietly assumed "the tech is ready" and "we can turn it on" were the same milestone. They are not when you sell a regulated product, and our launch checklist now treats compliance sign-off as a gate in its own right rather than a formality running in parallel.

How do you ship a loyalty mechanic in days, not months?

The pattern generalises, and none of it depends on ripping out the financial core. In order:

  1. Model loyalty rules as versioned configuration in one service. A new earn rule should be an edit and a review, not a code change queued into a release train. If a mechanic needs a deploy, you have built an engine, not a ruleset.
  2. Put earn triggers on the same event bus as the operational events. Orders, deliveries and empties should already be on the bus; then eligibility — including physical conditions like returnables coming back — is a read, not a fresh integration.
  3. Recompute points liability nightly from the event log. Give finance a number they can reconcile the next morning, so a mechanic's cost is visible before it compounds rather than after quarter close.
  4. Separate "deployed" from "enabled" with a per-market flag. Dark-launch everywhere, enable per market, and keep rollback to a single switch instead of a rollback release.
  5. Make compliance sign-off an explicit go-live gate. Build the per-market legal review into the launch checklist as its own step, so the flag never flips ahead of the lawyers. The same async-not-blocking instinct that let us run credit checks without blocking the order flow applies here: do the slow check in parallel, but never pretend it is optional.

Five days is not the number we are chasing; it is the floor that changes what a marketing team is willing to ask for. When a mechanic costs a week instead of two quarters, the questions get braver — seasonal combos, returnables-linked tiers, per-route offers that expire when the truck leaves. The next thing we are wiring is eligibility scored live at order capture, so a rep sees the double-points combo light up while the empties are still being counted, rather than the customer discovering it on next month's statement. That only stays cheap if the rules stay config and the events stay on the bus.

Frequently asked questions

Do we have to replace our loyalty platform to ship mechanics this fast?

No. The speed comes from where the rules and events live, not from a specific product. Model loyalty rules as versioned configuration in one service, and put earn triggers on the same event bus as orders and empties. Your financial core stays put; only the loyalty logic changes.

How do you stop a new mechanic from blowing up the points liability?

Recompute the outstanding liability nightly from the event log rather than forecasting it in a spreadsheet reconciled at quarter close. The morning after a mechanic goes live, finance sees exactly how much the number moved and can reconcile it against issued and redeemed points before the cost compounds.

If the build took five days, why did go-live take longer in some markets?

Because compliance is not a technical step. Loyalty mechanics that reward buying more alcohol are regulated differently per market, and in two markets legal review ran weeks past the build. A per-market flag let the mechanic sit dark until sign-off, so going live was one switch, not a fresh release.

Stuck with exactly this?

BrewOS builds the full route-to-market stack for global brewers — order capture, stock, loyalty, returnables, delivery and analytics on one event bus, run by a team of ~20 engineers. Bring us the feature that’s been stuck the longest and we’ll show you how we’d ship it in days.

Book a 30-minute walkthrough