Mobile Event Ticketing App Development
Main technical pain of ticketing app — concurrent sales. When 500 people simultaneously click "Buy" on last 10 seats, app must correctly handle this without double sales, hangs and incorrect statuses. Not frontend task — this is designing server with pessimistic locks or reservation via queue. But mobile client must also be ready for "seat already taken" scenario.
Seat Reservation and Race Condition
Standard scheme: user selects seat → server creates reservation with 10-minute TTL → user pays → reservation converts to ticket. If payment doesn't complete in 10 minutes — seat released.
On mobile client reservation timer is CountDownTimer (Android) or Timer.scheduledTimer (iOS), synchronized with server TTL. Not with moment button clicked on client, but with reservation.expiresAt from server response. Time zone difference and system clock drift on device kill UI timer if synchronized wrong.
// Android: timer sync with server expiresAt
class ReservationViewModel : ViewModel() {
private val _timeLeft = MutableStateFlow(0L)
val timeLeft: StateFlow<Long> = _timeLeft
fun startCountdown(expiresAt: Instant) {
viewModelScope.launch {
while (true) {
val remaining = ChronoUnit.SECONDS.between(Instant.now(), expiresAt)
if (remaining <= 0) {
_timeLeft.emit(0)
onReservationExpired()
break
}
_timeLeft.emit(remaining)
delay(1000)
}
}
}
}
On reservation expiry — don't just show error. Auto-suggest nearest available seats if real-time stream (WebSocket or SSE) supports it.
Venue Map and Interactive Hall
For concert halls and theaters need interactive scheme. On iOS — UICollectionView with custom UICollectionViewLayout or Canvas in SwiftUI for non-standard geometry. On Android — Canvas + GestureDetector for pinch-to-zoom.
Scheme loads as JSON with coordinates of each seat, section and status (available, reserved, sold, disabled). Real-time status updates via WebSocket: once someone reserves seat, all connected clients get { type: "seat_reserved", seatId: "A-15" }.
SVG venue maps — popular option for cross-platform solutions. React Native with react-native-svg or Flutter with flutter_svg + GestureDetector render SVG with tap-on-elements capability.
Electronic Tickets and Entrance Validation
Each purchased ticket gets unique UUID and QR code, generated on server. No need to store secret in QR — enough ticketId, verification happens on server on scan. QR shouldn't be static PDF image — generate dynamically from ticketId on client via ZXingObjC (iOS) or zxing-android-embedded, so don't store raster image in database.
Controller app — separate screen or separate app with AVFoundation/CameraX scanner, POST /tickets/{id}/validate, response: valid / already_used / invalid. Cache validated ticketId locally on controller device for no-internet case — sync after connection restored.
Payment Flow
Acquiring — YooKassa, CloudPayments or Stripe. On iOS additionally Apple Pay (PKPaymentRequest), on Android — Google Pay. For b2b segment — invoice via email with SBP payment.
After payment immediate PDF ticket send to email via SendGrid/Postmark and push via FCM/APNs with deep link to "My Tickets" screen.
Typical Errors
Double booking. Without SELECT FOR UPDATE or distributed lock at reservationId + seatId level two users can create reservation for same seat. On PostgreSQL — advisory locks or ON CONFLICT DO NOTHING on reservation insert.
QR on screenshot. Don't put screenshot protection — breaks UX. Instead QR should be one-time on validation: first scan — OK, second — already_used.
Timeline and Stages
Design data model (halls, sections, seats, events) → venue map → reservation with TTL → payment → electronic tickets → controller app → load testing.
6–10 weeks for full app with interactive venue map, real-time updates and controller app. Cost calculated individually after requirements analysis.







