If you told me a few years ago that I’d end up building a fully secure, enterprise-grade, slot-machine-looking, real-time lucky draw system for one of Langkawi’s biggest annual events…
I’d probably say:
“Bro, you sure you got the right tech guy? I fix servers at 3am, not spin jackpot wheels.”
But here we are.
Langkawi Bike Fest 2025 needed a system.
Not just any system.
A high-traffic, real-time, payment-validated, audience-screaming, event-critical lucky draw platform.
And like any tech wizard who drinks coffee at the wrong hours, I said:
“Aight. Let’s build something gila sedap.”
The Chaos They Wanted Me to Tame
The requirements list was basically the Avengers of technical pressure:
-
Thousands of walk-in registrations during peak hours
-
Real-time big-screen lucky draw with smooth visuals
-
Payment validation using Chip-In
-
Multi-role access for event staff
-
Full audit trail for compliance
-
Security strong enough to make hackers feel useless
-
Zero duplicate Lucky Draw IDs under heavy load
Basically:
“Build something reliable enough to run in front of thousands of bikers who can smell nonsense from 3km away.”
Mission accepted.
With fear.
But accepted.
My Weapon of Choice: Laravel 11 (Because Self-Punishment Is Not My Brand)
Tech stack that powered the beast:
-
Laravel 11 + PHP 8.2
-
MySQL 8
-
Tailwind + Alpine.js
-
Redis for cache
-
Docker for deployments
-
Chip-In payment gateway
-
Vanilla JS for high-performance animation
Laravel kept everything clean, fast, and maintainable — especially important when you’re building something that will be watched live by an entire festival crowd.
Walk-In Registration: Fast, Furious, and Race-Condition-Free
The registration system had one job:
Handle hundreds of submissions at the same moment without panicking.
So I used:
lockForUpdate()
This prevented duplicate lucky draw IDs even when everyone and their cousin pressed “Register” together.
Think of it like “Oi bro, tunggu turn!” but for the database.
Each ID is generated sequentially (A00001, A00002, …).
Midnight hits — system auto-expire, auto-reset.
No manual cleanup, no drama.
The Big Screen Lucky Draw Experience
This part was my guilty pleasure.
I built a custom slot-machine digit animation using pure vanilla JavaScript.
No frameworks, no heavy bundles — just performance-focused code:
-
Digit-by-digit spinning animation
-
Big, bold visual design
-
Winner details popup
-
Confetti
-
Smooth like butter even on giant LED screens
People actually shouted during testing.
Good sign.
Payment Validation: Choose Your Fighter Mode
Chip-In offers multiple ways to verify payments — so I built the system to support all of them cleanly, using a Strategy Pattern:
-
Webhook Mode (Production – real-time, HMAC-secured)
-
Callback Mode (Staging / redirect-based)
-
Polling Mode (Fallback – checks status every 2 minutes)
Everything neatly isolated:
class WebhookValidator implements PaymentValidator
Flexibility = no surprises later.
And no late-night panic debugging.
Security: As Tight As a BMW Engine Bolt
This system is built like it’s going to war:
-
CSRF protection
-
XSS filtering
-
Strict password policies
-
Role-based access
-
Race-condition-safe ID generation
-
HMAC verification for all webhooks
-
Rate limiting for all endpoints
-
Input validation on every form
-
Audit logs recording every critical action
Basically:
If someone tries anything funny, system will say “Not today, boss.”
Admin Roles: Because Not Everyone Should Touch the Important Buttons
I built 3 clear roles:
👑 Superadmin
Full access, system settings, all controls.
🧑💼 Manager
Handles draws + registrations but no system-level settings.
👷 Staff
Handles registrations only.
Clean separation, zero confusion, no “Eh siapa tekan ni?” moments.
All enforced with Laravel Gates.
Performance: Smooth Even During Event Madness
Behind the scenes:
-
Optimized indexing
-
Eager loading
-
In-memory caching
-
LocalStorage caching
-
Tailwind purge
-
Minimal JavaScript footprint
-
Adaptive polling
The result?
A system that stayed cool even when the event crowd wasn’t.
What I Learned While Wrestling This Beast
1. Design for concurrency first
Not last.
2. Payment systems demand flexibility
Never assume “one method only”.
3. UX matters
If the screen looks boring, excitement dies.
4. Good security is invisible
Users don’t see it — but they definitely feel it.
5. Document early
Future Zabel will appreciate past Zabel’s sanity.
The Final Result
This system successfully handled:
-
High-traffic registrations
-
Real-time live draw
-
Secure payment flows
-
Multi-role event staff operations
-
Full audit logging
-
Production-level security
-
Happy organizers
-
Even happier participants
And yes…
Now people call me the “Lucky Draw Tech Guy”.
I’m choosing to accept that title with pride.
What’s Next?
Future upgrades I’m planning:
-
2FA for admins
-
CSP headers
-
Security scanning in CI/CD
-
Real-time WebSockets
-
Dedicated staff mobile app
-
Full analytics dashboard
Because a system this powerful deserves evolution.
Closing Note
If you ever need someone to build a high-stakes, event-critical system that must not fail…
Just remember:
I built a lucky draw system that survived Langkawi Bike Fest 2025.
That says enough.