Building Hayyak
How I built a multi-tenant hotel management system that integrates with Opera PMS (OHIP), processes payments through dual gateways, and delivers real-time reservation updates via Firebase and WebSockets.
01The Problem
Hotelsrunonfragmented,agingsystems.
The hospitality industry is dominated by Opera PMS — a powerful but complex property management system that most hotels already run. The challenge isn't replacing it; it's integrating with it. OHIP (Oracle Hospitality Integration Platform) provides the API layer, but it demands careful handling: the sync between your application's state and the PMS must be reliable, retryable, and never leave reservations in an inconsistent state.
On top of this, Hayyak needed to support multiple hotels as independent tenants — each with its own configuration, staff, room inventory, and payment credentials — without any cross-contamination of data. And it needed to collect payments through two gateways (Tap Payments for primary, HyperPay as fallback), keeping reconciliation clean across both.
The guest experience layer added another dimension: identity verification at check-in, push notifications for every reservation state change, and real-time WebSocket updates for front-desk staff — all while maintaining full Arabic and English support.
Core requirements
- Bidirectional sync with Opera PMS via OHIP API — reliable and retryable
- Multi-tenant isolation: each hotel is a fully independent configuration unit
- PCI-compliant payment flows through Tap Payments and HyperPay
- Guest identity verification at check-in
- Real-time push notifications (Firebase) and WebSocket updates for staff
02Architecture
Fivelayers.Twogateways.Onesourceoftruth.
The system treats Opera PMS as the authoritative record and uses async Celery tasks to keep Hayyak's database in sync — with retry logic for OHIP timeouts and dead-letter queuing for failed syncs.
Guest Mobile App / Web Interface
Reservation, check-in, check-out flows — bilingual Arabic & English
Django 5.1 REST API
Multi-tenant request routing, Knox auth, Swagger-documented endpoints
Opera PMS (OHIP Integration)
Two-way sync with hotel property management system via OHIP API
Payment Gateway Layer
Tap Payments (primary) + HyperPay (fallback) — PCI-compliant flows
Firebase + WebSocket Notifications
Push notifications for booking updates, real-time status changes
Celery (async)
Email confirmations, payment reconciliation, OHIP sync retries — all off the request cycle
03Key Decisions
Whatwechoseandwhy.
Per-hotel tenant isolation via database-level config
Shared-schema multi-tenancy (a hotel_id column on every table) is simpler to build but fails at isolation — a query bug or missing filter leaks data across tenants. We implemented per-tenant configuration objects stored in the database, with middleware that scopes every request to the authenticated hotel's data partition.
OHIP integration with Celery retry and dead-letter queue
Opera PMS OHIP has real-world latency and occasional timeouts. Synchronous OHIP calls in the request cycle would make every reservation action unreliable. We moved all OHIP communication to Celery tasks with exponential backoff retry and a dead-letter queue for manual review of persistently failed syncs.
Dual payment gateway with automatic failover
Tap Payments is the primary gateway for the Saudi market. HyperPay serves as a hot standby. If a Tap Payments request fails with a gateway error (not a card decline), the system transparently retries through HyperPay. Both gateways use tokenized transactions — no card data ever touches our database.
Knox token auth over JWT for mobile clients
JWT tokens cannot be revoked without a blocklist. For a hospitality app where staff turnover is common and devices get shared, server-side token revocation is a hard requirement. Knox stores tokens in the database, making immediate revocation a single DB delete — clean and auditable.
04Outcomes
Enterprise-gradehospitality,fullyintegrated.
Tenant hotel isolation
Each hotel is a fully isolated configuration unit
Payment gateways integrated
Tap Payments + HyperPay with automatic failover
Compliant payment flows
No card data stored — tokenized transactions only
Time reservation updates
WebSocket push across guest, staff, and PMS
05Challenges & Lessons
Wheretherealcomplexitylived.
OHIP state reconciliation
OHIP can return stale state during high load. We built a reconciliation job that runs nightly, comparing Hayyak's reservation records against OHIP's source of truth and flagging discrepancies for manual review.
Payment reconciliation
Two gateways mean two transaction logs. Building a unified reconciliation view that correctly attributes each transaction — handling partial refunds, gateway retries, and currency rounding — was the hardest accounting problem in the project.
Identity verification at scale
Guest identity verification (ID scan at check-in) needed to be fast enough to not slow hotel front desks. We offloaded verification to an async background task with an optimistic 'pending verification' state shown immediately.