Loyalty & Members · Points & Tiers
Turn one purchase into the next — loyalty that compounds.
A points program is a financial liability on your books. If it double-credits, leaks past expiry, or bypasses its own caps, it costs you money and trust. Flash's engine is built for one thing first: correctness.
The problem
A leaky points engine quietly bleeds margin.
The failures that hurt most are the invisible ones — a retry that credits twice, a cache outage that drops a cap, points that should have expired but didn't. Each one is real money leaving the business.
Double-credited awards
A network retry or a re-run worker awards the same purchase twice — and your liability quietly grows.
Caps that fail open
When the cache that tracks daily limits blips, a naive engine just keeps awarding — the cap silently disappears.
Tiers that drift
Status computed off a moving balance, or expiry that runs out of order, leaves members at the wrong tier and disputes in support.
How it works
Correctness is a mechanism, not a promise.
Every balance and tier mutation is serialized per member with a PostgreSQL advisory lock. Awards are idempotent. Spending is FIFO. Caps fail closed. None of it is left to chance.
Shared award path
One capped, idempotent award — for every source.
calculateReceiptPoints
amount × base rate × tier multiplier, with min-amount floor
applyDailyCap
reads the Redis daily accumulator
earnPoints (advisory lock)
idempotency key — a key hit writes nothing, returns the existing amount
increment accumulator
only on a fresh award
Fails closed. If the Redis cap tracker is unreachable, the award is withheld (nothing written) — a cache outage can never silently disable the cap.
The same helper backs receipt OCR, Shopify orders, and marketplace orders — so the cap is enforced once, everywhere.
Tier engine
Upgrades on rolling-12-month earned points.
Re-upgrade bonus
Re-qualify after a demotion within the window → a bonus batch is paid.
Grace on downgrade
Fall below the maintain threshold → one rank down, after a grace period with warnings.
Tier math uses earned points over a rolling 12 months — not current balance — so spending rewards never silently demote a member.
FIFO consumption
Spending draws from the member's oldest non-expired batches first (FOR UPDATE), skipping expired or zero batches — and throws before any mutation if the balance is short.
Idempotent ledger
A per-member advisory lock serializes balance changes; on an idempotency-key hit the ledger returns the existing amount and writes nothing, so derived records stay consistent.
Auditable allocations
Each FIFO draw is persisted to a consumption-allocations table, so you can always show exactly which points were spent when.
Why it's different
Reward real spend, everywhere — accounted for correctly.
Most loyalty apps reward on-site actions on one storefront. Flash awards points from verified purchases across channels — and runs them through one engine engineered so the numbers always tie out.
Typical approach
On-storefront points engines
Reward clicks and purchases on a single storefront.
Flash, by design
Receipts, Shopify, and marketplace orders all earn through one shared, capped award path.
Typical approach
Naive award logic
A retried request can credit the same purchase twice.
Flash, by design
Advisory-locked, idempotency-keyed awards — a duplicate writes nothing and returns the existing amount.
Typical approach
Cache-dependent caps
If the limit tracker is down, awards keep flowing past the cap.
Flash, by design
Fails closed by design — the award is withheld rather than silently bypassing the cap.
Built for integrity
The innovation here is rigor, not a chatbot.
This module's value isn't AI — it's a financially correct points ledger. Concurrency control, idempotency, and fail-closed behavior are the features, because they're what keep your liability accurate.
Serialized by advisory lock
Per-member pg_advisory_xact_lock means concurrent awards, spends, and tier checks can't race or corrupt a balance.
Real-time tier evaluation
Upgrades fire on a real rank increase from rolling-12-month earned points and emit events after commit; downgrades run in batches with a grace period.
Resilient workers
Expiry scanning, tier evaluation, birthday and re-engagement bonuses run as a worker fleet — each member failure isolated, never blocking the batch.
What changes for the business
A points liability you can trust on the balance sheet — and a tier ladder that genuinely reflects who your best members are.
FIFO
oldest points spent first, FOR UPDATE locked
Fail-closed
caps hold even when the cache is down
Idempotent
no award is ever double-credited