
Event-Crypt is a multi-tenant platform for organization-scoped award voting and ticketing events. I built the Vue + Inertia web app, the Laravel backend (payments, USSD, admin), and the operational setup (CI/CD, Nginx + PHP-FPM, workers) to run it reliably in production.
My Role
Full-Stack Engineer (Web · Backend · DevOps)
Duration
2026
Context
Multi-tenant Product
Outcome
Web + USSD · layered payment verification · queue/scheduler reconciliation · CI/CD + Nginx/PHP-FPM deployment
Stack
Context
Organizations running awards and ticketed events need a single platform where each organization can create events, collect votes and ticket purchases, and reliably reconcile payments across multiple user channels.
The Pain
Payments can be inconsistent when webhooks are delayed, duplicated, or missed. USSD sessions require a deterministic state machine, and multi-tenant boundaries must be enforced everywhere (routes, queries, admin).
Why It Mattered
Incorrect fulfillment (missing votes, duplicate votes, unfulfilled tickets) breaks trust and directly impacts revenue. The system must be auditable and resilient under provider variability.
Technical Goals
Constraints
Clients (web, admin, USSD gateway) talk to a Laravel monolith with domain services for voting, ticketing, payments, and notifications. Payments integrate primarily with Hubtel, with layered verification (webhook + success verification + scheduled reconciliation). Data is stored in PostgreSQL, and async workloads run via queue jobs and the Laravel scheduler.

Scroll horizontally on smaller screens to view full diagram
Web App (Vue 3 + Inertia)
Voting and ticketing UI for end users.
USSD Gateway Integration
USSD voting channel via /api/ussd and a session state machine.
Laravel Monolith
Routes/middleware, controllers, domain services, and queued jobs for voting/ticketing/payments.
Nginx + PHP-FPM
Production runtime: serves the web app and API, and runs queue workers and scheduled jobs alongside the app.
Filament Admin Panels
Organization-scoped operations: event setup, nominee management, verification, monitoring.
PostgreSQL
Primary datastore for tenants, events, votes, tickets, and payments.
Queue + Scheduler
Runs verification jobs and periodic reconciliation for pending payments.
Hubtel + Paystack
Payment initialization, status checks, webhooks, and (legacy) parallel payment support.
SMS Providers
Delivers receipts/notifications for successful votes and ticket purchases.
Cloudinary
Media storage and delivery for event assets.
→Layered payment verification
Combining webhook processing with success-page verification and scheduled reconciliation reduces lost-payment risk and improves eventual consistency.
→Cache-backed USSD state machine
USSD is conversational and stateless per request; caching session state makes flows deterministic and resilient.
→Tenant scoping in routes + queries
Multi-tenancy must be enforced consistently to prevent data leakage across organizations.
The platform is organized as a Laravel monolith with domain services, async jobs, and clear boundaries to external providers.
flowchart LR
subgraph Clients
WEB["Web Browser<br/>Voting/Ticketing"]
USSDGW["USSD Gateway/Telco"]
ADMIN["Admin/Super Admin<br/>Filament UI"]
end
subgraph App["Laravel Monolith"]
ROUTES["Routes + Middleware"]
CTRL["Controllers"]
SVC["Domain Services<br/>Hubtel, Voting, Receipt, Notifications"]
JOBS["Queue Jobs + Scheduler"]
MODELS["Eloquent Models + Scopes"]
CACHE["Cache Store"]
end
subgraph Data
DB["PostgreSQL / SQLite"]
end
subgraph External
HUBTEL["Hubtel APIs<br/>Checkout / Status / Send Money"]
PAYSTACK["Paystack APIs<br/>Legacy/parallel support"]
SMS["SMS Providers<br/>Hubtel/Arkesel"]
CLOUD["Cloudinary"]
CI["GitHub Actions CI"]
end
WEB --> ROUTES
ADMIN --> ROUTES
USSDGW --> ROUTES
ROUTES --> CTRL --> SVC --> MODELS --> DB
CTRL --> CACHE
SVC --> CACHE
SVC --> HUBTEL
SVC --> PAYSTACK
SVC --> SMS
SVC --> CLOUD
JOBS --> SVC
JOBS --> DB
JOBS --> HUBTEL
CI --> AppPayments are fulfilled via a layered approach to minimize missed callbacks and handle provider variability.
sequenceDiagram
participant U as Voter (Web)
participant FE as Vue + Inertia
participant BE as Laravel Controllers/Services
participant HP as Hubtel Checkout
participant WH as Hubtel Webhook
participant JOB as Verification Jobs
participant DB as Database
U->>FE: Select nominee/category + quantity
FE->>BE: Submit vote checkout request
BE->>DB: Create pending payment
BE->>HP: Initialize checkout
HP-->>U: Checkout URL / redirect
U->>HP: Complete payment
HP->>WH: Payment callback
WH->>BE: Process webhook payload
BE->>DB: Mark payment successful
BE->>DB: Create votes + increment nominee totals
Note over JOB,BE: Fallback verification runs if webhook delayed/missedUSSD requests are processed through a cache-backed state machine keyed by session ID.
sequenceDiagram
participant T as Telco/USSD Gateway
participant UC as UssdController
participant C as Cache
participant HS as HubtelService
participant DB as Database
T->>UC: /api/ussd (new session)
UC->>C: Create ussd_state_<sessionID>
T->>UC: User code/category/quantity/confirm inputs
UC->>C: Update session state per level
UC->>DB: Create pending payment
UC->>HS: Charge mobile money
HS-->>UC: Prompt/PIN/OTP status
UC-->>T: Continue/end session responseI handled the deployment and operational setup so the platform could run reliably in production.
The Problem
Payment providers may retry webhooks and users may refresh/return to success pages, causing duplicate fulfillment risk.
The Fix
Implemented idempotency guards around payment fulfillment (status checks and usage checks) so votes/tickets are created exactly once per successful transaction.
The Problem
Multi-tenant systems can accidentally leak data if organization scoping is inconsistent.
The Fix
Scoped public routes by organization slug and enforced ownership checks and scoped queries throughout controllers and admin panels.
A resilient multi-tenant platform that supports both web and USSD channels with reliable payment fulfillment and admin operational tooling.
Before → After
Payment completion paths
Admin operations
Channel support
Business Outcome
Organizations can run multiple award and ticketing events in one platform, reconcile payments reliably, and operate events with admin verification tools and notifications.
Would Do Differently
Key Takeaways
Next Project
Backend Engineering
