Hey devs! Remember when I said I'd keep my project CFFBRW simple? Well, turns out distributed systems don't care about your feelings.
So I built this global variable feature - basically Redis but worse (I'm kidding... mostly). Users wanted to share state between API workflows, and I thought "how hard could it be?" Famous last words.
The Fun Before The WHAT-THE-HELL
So a friend wanted a gamification banner - "Wheel of fortune, only 10 '20% off' vouchers available daily!" Simple enough. I whipped up an API workflow in 15 minutes:
- Check inventory
- If voucher stock is available, return wheel config
- Deploy for โก SPEED โก
It was beautiful. It was fast. It was also giving vouchers to 47 users because race conditions don't care about your business logic.
How I Burned Through Vouchers Faster Than My Free-Tier Credits
Picture this:
10:00:01 - User 1st: "Vouchers available: 10?" Yes! (Chance to win = 50%)
10:01:15 - User 10th: "Vouchers available: 7?" Yes! (Chance to win = 50%)
10:02:38 - User 20th: "Vouchers available: 5?" Yes! (Chance to win = 50%)
...
10:05:0... - User 47th: "I deserve a voucher! Because I won."
And then the banner was paused.
By the time the writes reconciled, we'd given away 37 extra vouchers. My friend was... not thrilled. ๐
So demo failed. Too early, yes, but he is my friend, so... Teehee!
I know that there are technologies/products to address this. But I hold back myself from adding things so that CFFBRW can be as cheap and light and fast to run as possible.
And when you limit your options, you rack your brains. After some frantic Googling and some "vibe-asking", I discovered some reconciliation strategies for the component.
The 4 Reconciliation Strategies That Could've Saved My Sanity
1. last-write-wins
(The YOLO Strategy)
The default. Whatever wrote last is the truth. Great for settings, but BEWARE: Not for anything critical.
- Use case: User preferences, feature flags
2. sum-increments
(The "Actually Count Everything" Strategy)
Instead of setting values, you track increments. All increments get summed during reconciliation.
- Use case: Page views, API calls, VOUCHER COUNTERS (๐ญ)
- My case: Would've correctly counted all 47 winners. Demo saved.
3. merge-objects
(The "Keep Everything" Strategy)
For JSON objects, merge all updates together. Conflicts on same field? Usually last-write-wins per field.
- Use case: User profiles, shopping carts, collaborative data
- My case: Not applicable, but imagine if there were multiple vouchers with different winning chances...
4. max-value
(The "Only Up" Strategy)
Always keep the highest value seen. Like a high score that never goes down.
- Use case: Versioning, sequence numbers, "highest bid" scenarios
- My case: Would've jumped straight to 47, at least I'd know the damage immediately
What I Actually Actually Learned
- Default settings are defaults, not solutions - Last-write-wins is fine until it's not. And a big Beware/Caution is needed.
- Test with concurrency - My demo with one request at a time? Adorable. Be more test-driven, especially with vibe.
- Math > Vibes - "It'll probably be fine" is not a reconciliation strategy. As anyone knows, I've been learning to code for the last two years in my free time. And more than ever, you need to spend time to actually learn.
- Edge computing is fast - Fast enough to create race conditions you didn't know existed, and cheap enough to get you hooked and locked in.
The fix was simple - switched to sum-increments
for anything involving counting. But I don't think it actually addresses all the issues. It only gives me a good enough solution.
Current Status
Still shipping, still learning. The gamification banner now works perfectly.
Building in public means learning in public, admitting your limitations in public, regretting a bit in private, and learning more.
P.S. - If you're like me and don't know these things, I hope we can learn something new. Set up your reconciliation strategy BEFORE deploying to production. Your wallet will thank you. And if you already know this, guide me some.
P.P.S. - Now my motto is "Move fast but scale correctly."
Top comments (0)