How I Accidentally Became the ‘Lucky Draw Guy’ of Langkawi Bike Fest 2025

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:

  1. Webhook Mode (Production – real-time, HMAC-secured)

  2. Callback Mode (Staging / redirect-based)

  3. 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.

Previous Article

How I’m Turning Telaga Seafood Into a Digital-First Restaurant 🦑💻

Next Article

How I Built a Real-Time RORO Eligibility Checker for Langkawi Bike Fest 2025

Write a Comment

Leave a Comment

Subscribe to our Newsletter

Subscribe to our email newsletter to get the latest posts delivered right to your email.
Pure inspiration, zero spam ✨