← Michael Siddiqi

Hotel self-service check-in kiosks

99.8% uptime across payments, passports, keycards, and five lock-system vendors.

React NativeTypeScriptAndroid native modulesAdyenPMS integrations
Hotel self-check-in kiosk app on a tablet

One app, many hotels

Every hotel runs different infrastructure: different property-management systems (Mews, OHIP, and others), different door locks, different payment setups. The kiosk had to present one consistent guest experience — find your booking, pay, get your key — on top of whatever combination a given property runs. A guest at 1 a.m. doesn't care which PMS the hotel chose; they care that the machine gives them a room key.

Stay length selection screen
Booking confirmation screen

Five lock vendors, one abstraction

The hardest engineering problem was the door locks. Five vendors — Saflok, Salto, Visionline, Onity, Vostio — each with its own SDK, its own model of what a key is, and its own failure behavior. Designing a single abstraction over five systems that only mostly agree meant deciding, case by case, what belonged in the shared interface and what had to stay vendor-specific behind it. The SDKs are bridged into React Native through Android native modules, alongside the passport scanners and keycard encoders, so the UI code never knows which vendor it's talking to.

The failure modes that mattered

Three fronts, in practice. Payments: Adyen terminal timeouts, pre-authorization edge cases, and refund flows, where the rule is that no guest ends up charged without a completed check-in. Passports: documents the scanner can't read, hardware quirks, and verification edge cases, handled with clear retry paths instead of dead ends. And the PMS: bookings that don't appear or reservation data that's stale by the time the guest is standing at the kiosk, which taught me to treat the PMS as a source of truth that must always be re-verified, never assumed.

Uptime as a feature

A kiosk that's down at 1 a.m. means a guest who can't get into their room. The 99.8% figure came from three layers: defensive handling around every hardware interaction, so a misbehaving encoder or scanner degrades a step instead of crashing a session; monitoring with fast response, so problems were often fixed before a guest met them; and graceful fallback, so when the kiosk genuinely can't finish, it hands the guest to reception with context instead of a frozen screen.

Key collection screen

What I'd do differently

Two things. The lock-vendor abstraction should have existed from the first integration, not been unified after several were already live — retrofitting an interface across shipped vendor code is much harder than growing one. And remote diagnostics deserved earlier investment: when your software runs on a tablet in a hotel lobby three cities away, the ability to see exactly what the machine sees is worth more than almost any feature.

Previous case study: Flytoget ticket vending machines →