From interest to a usable ticket
Browsing and cart state remain lightweight until checkout, when inventory becomes a transactional concern.
Platform Engineering · Event Ticketing
An East African event platform spanning public discovery, checkout-time ticket reservation, organizer operations, ticket issuance, transfer, and entry validation.
Product surface
The attendee side needs fast event discovery and a dependable checkout and ticket experience. The organizer side needs control over events, inventory, promos, holds, and operational state. Both depend on the same transaction model underneath.
System model
The system has to preserve buyer intent without overselling organizer inventory. That means cart state, reservations, orders, issued tickets, and entry scans cannot be treated as unrelated screens or CRUD records.
Three connected lanes
Each lane has different UX concerns, but the platform has to keep all three aligned around the same event and order state.
Browsing and cart state remain lightweight until checkout, when inventory becomes a transactional concern.
Redis locks, PostgreSQL transactions, order state, and ticket validation boundaries protect the same inventory from races.
Organizer tooling covers event lifecycle, ticket types, pricing, promotional rules, holds, and event-level operational metrics.
Checkout & inventory
The platform deliberately does not reserve inventory when a buyer adds a ticket to the cart. Reservation begins at checkout, where intent is strong enough to justify temporarily removing capacity from other buyers.
Order lifecycle
Redis locking and database transactions protect inventory and order state while the checkout flow moves toward completion or release.
Buyer intent only; inventory is not reserved yet.
Checkout reserves ticket capacity for the pending order.
Create the pending sale with customer and ticket context.
Complete or cancel the order through one authoritative transition.
Create ticket records only after the order reaches the completed state.
Queue ticket PDFs and buyer notifications after completion.
Frontend architecture
The frontend uses Next.js 16 with localized routes, explicit server-state and client-state boundaries, strict form validation, performance work, and an installable PWA foundation.
Frontend stack
React Hook Form and Zod handle form contracts alongside these broader application boundaries.
App Router, localized routes, public product surfaces, protected organizer routes, and SEO.
English and Kiswahili routing are part of the application model rather than a later translation layer.
TanStack Query owns server state while Zustand handles focused client-side state.
Manifest and service-worker tooling establish an installable, offline-aware browser foundation.
Backend architecture
The Fastify backend is intentionally a single deployable application, but domain modules keep authentication, event management, organizations, ticketing, and background jobs from collapsing into one undifferentiated service layer.
JWT access/refresh flows, verification paths, permission rules, rate limiting, and security-oriented Fastify plugins.
Event lifecycle, public discovery, organizer editing, ticket types, pricing, promo codes, holds, and event-level metrics.
Organizer ownership and membership boundaries keep operational access scoped to the correct organization.
Cart, checkout reservation, orders, inventory, ticket records, dynamic QR validation, entry OTPs, scan logs, and transfers.
BullMQ-backed work queues separate ticket PDF generation and buyer notifications from synchronous request handling.
Ticket integrity
Issuing a QR image is not the end of the security model. Entry validation combines short-lived QR data, a separate entry factor, concurrency protection, and scan history so the system can distinguish a valid ticket from an expired, duplicated, or wrong-event attempt.
Entry controls
The same ticket can also move between people through an explicit transfer lifecycle rather than silently editing ownership data.
Ticket UUID, short-lived TOTP data, and timestamp rotate the scannable payload.
A hashed entry OTP has its own expiry and must validate alongside the ticket QR state.
Rate limits, Redis locking, ticket state checks, and scan logs protect concurrent entry attempts.
Claim tokens, transfer limits, cancellation, history, and guest/authenticated claiming preserve provenance.
Delivery & operations
The backend repository carries its operational path with the code: integration-service dependencies in CI, container builds, staged deployment, migration preflight, health checks, and a production backup gate.
Delivery path
Security scans are present as visibility controls; the current npm audit and optional Snyk steps are non-blocking rather than being described as hard release gates.
PostgreSQL 16 and Redis 7 service containers support lint, type checks, tests, and build verification.
GitHub Actions builds the application image and publishes deployment artifacts to GitHub Container Registry.
Migration preflight, database migration, container recreation, and local/public health checks run in deployment.
The production path is manually dispatched and creates a database backup before migration and deployment.
Engineering evidence
The implementation repositories are private. This case study exposes the architecture, transaction model, security boundaries, and delivery controls without publishing proprietary source code.
Next.js 16 App Router, English/Kiswahili routes, public event/cart/ checkout/ticket surfaces, organizer dashboard routes, PWA tooling, and the live Ticket Trove product.
Fastify modules, checkout-time reservation, Redis locks, atomic order completion/cancellation, ticket validation, transfer workflows, background jobs, and PostgreSQL migrations.
Test dependencies, Docker builds, GHCR delivery, deployment migrations, health checks, failure alerts, Sentry integration, and the production backup step are represented in repository workflows.
Evidence boundary
The case study intentionally avoids presenting planning targets or incomplete surfaces as shipped proof.
Ticket Trove Africa
Inventory concurrency, mobile entry, language, connectivity, and organizer operations all influence the architecture.