Inflyter

The digitalisation of an industry that had barely any online presence, built as a single platform connecting travellers to duty-free retailers.

I built the platform from scratch: backend, REST API, admin back office, two iOS apps (B2C and B2B), web marketplace, and cloud infrastructure. 12+ airports live, 5 major retailers integrated, £1.7M+ raised across two rounds on this technology.

The architecture enabled the industry's first digital duty-free branded boutiques and powered a cruise retail proof of concept for Starboard Cruise Services.

PHPSymfonySwift (iOS)ReactHTMLCSSJavaScriptTypeScriptREST APIMariaDBPostgreSQLAWS Elastic BeanstalkAWS EC2AWS S3AWS RDSAWS LambdaAWS Route 53AWS SNSAWS IAMAWS CloudWatchDockerNginxJenkinsGitHub ActionsBashStripeAdyenSegmentFirebaseSendinblueJamf (MDM)Akeneo (PIM)IATA specsAVFoundationGit / GitHub
5

major duty-free retailers

12+

airports live across 3 continents

8

cruise lines onboarded

£1.7M+

raised across two rounds

Photo: Marketplace or Inflyter app screenshot

The Opportunity

Duty-free is a massive global industry worth billions. When we started in 2017, however, it had almost no online presence. No e-commerce, no way to browse or buy before arriving at the airport. Travellers walked into a shop, bought what they saw, and that was it. Nobody had built a platform to change that, largely because the complexity behind duty-free makes it extremely hard to digitalise.

Products are tied to specific flights, terminals, and gates. Purchasing rules change depending on your itinerary. Customs regulations vary by country. And every retailer runs completely different systems. All of this had to work together in a single platform.

Photo: Different retailer brandings or airport configurations

Travel-Aware Commerce

What a traveller can buy depends on where they're flying, which legs of their journey qualify for duty-free vs duty-paid, which terminal and gate they depart from, and sometimes which specific shop within that gate. Duty-free is not regular e-commerce. The rules change from one airport to another, and customs regulations add another layer of constraints on top.

The data model had to support all of this through configuration, not custom code per location. Product catalogues were scoped down to gate and shop level. Multi-leg flight itineraries determined purchasing eligibility. Customs compliance had to be built into the core workflow from the start.

Photo: Different retailer brandings or airport configurations

Parsing Travel Data

The platform needed to extract and parse data from boarding passes, passports, and booking emails, each with its own set of challenges.

The boarding passes use standard barcodes, but parsing the data was the harder part: IATA has published several versions of the boarding pass specification over the years, and not every airline follows the latest one, so the parser had to handle all of them. On top of that, not all legs of a journey appear on a single boarding pass, so a traveller might have two separate passes for what is actually one trip. I had to build logic to detect whether multiple passes belonged to the same journey or were completely unrelated flights.

The passport scanner was a different challenge because there's no barcode on a passport. I built an OCR pipeline to extract the MRZ from the document image, then parsed it against IATA standards to pull traveller identity and nationality data.

Beyond the app, I built an email parser so travellers could forward their booking confirmations and have their flight details imported automatically. This meant writing complex regex and pattern-matching logic to extract flight numbers, dates, airports, and itineraries from unstructured emails where none of this information sat in a predictable place or followed a consistent format.

Photo: iOS app screens montage

Retailer Abstraction

Every retailer had a different backend, different product formats, different ways of exchanging data, and different financial workflows for order reporting and reconciliation. Some had reasonably well-structured APIs, others sent manual product exports or expected file exchanges over FTP. To make things harder, they all dealt with different file formats: JSON, CSV, XLS, XLSX, or XML.

The original plan was to publish our API and let retailers connect to us, but their systems were too rigid to adapt, so we had to meet them where they were. I built a retailer abstraction layer: the marketplace worked with a single, consistent data model, and between that model and each retailer sat a custom connector that normalised their specific formats and protocols into something the platform could process. Adding a new retailer meant building a new connector, not touching business logic.

But it wasn't just a technical challenge: coordinating with teams across multiple countries and time zones, each with different cultures, communication styles, and levels of flexibility, was sometimes harder than connecting the systems themselves.

Photo: Architecture diagram or AWS infrastructure

Data Normalisation

Two retailers could stock the same product but with different descriptions, different images, and different product codes. Some sent valid UPC or EAN codes, others sent internal SKUs labelled as product codes. The user experience suffered: the same product looked completely different depending on who was selling it. On our side, it also made integration harder: matching products across retailers, detecting duplicates, and maintaining a consistent catalogue was nearly impossible without a shared standard.

To solve this, I wrote a custom product code validation library that could parse, validate, and normalise codes from different formats (UPC, EAN, internal SKUs) into GTIN, the universal product identification standard that none of the retailers were actually using. This made it possible to deduplicate products across retailers, index them consistently for search, and track the same product's performance across different shops and airports. It also flagged invalid identifiers that retailers had mislabelled as product codes.

With the library in place, I built a base product layer that sat above the retailer-specific data. Inflyter became the single source of truth for how products appeared, regardless of the supplier. Retailers could still customise product information per shop if they needed to, but the baseline was always consistent and controlled by us.

Onboarding a new retailer's catalogue went from weeks of manual cleanup to a largely automated process, with products normalised, deduplicated, and linked to the master record as they came in, regardless of how messy the source data was.

Photo: Different retailer brandings or airport configurations

Behind the Counter

Every retailer processed orders differently, and none of their workflows were compatible with ours. Since Inflyter owned the full order lifecycle, from placement through preparation, sealing, fulfilment, delivery, and refunds, we needed a unified process that could work across all of them. The goal was to make Inflyter orders feel like any other order for the store, just coming from a different source.

I built a dedicated B2B app for retail staff that made this possible. It walked staff through each order step by step: scanning and validating products, generating QR codes for sealed packages, and handing off to the customer or the locker system. The app ran on managed devices I configured through an MDM platform, locked down to prevent misuse.

The harder part wasn't building the app. It was getting people to adopt it. Every store had its own habits, and asking staff to change how they work required trust, training, and a tool simple enough that anyone could pick it up without friction.

Photo: Presentation setting or team photo

From 1 to 12

The early integrations were each a custom project. Even within the same retail group, different airports had different integration paths, meaning we sometimes had multiple connectors for a single retailer.

This approach couldn't scale, so I designed a standardised onboarding process with automated catalogue syncing, PIM integration, and a consistent connector template. Opening a new airport became a configuration task, not a development project.

Configuration handled the heavy lifting, which freed us to focus on the regional specifics that still needed abstracting: local payment providers, regulatory differences, and teams that each worked very differently. The platform had to handle all of it through configuration, not custom code.

It took years to build a platform mature enough to be fully retailer-agnostic and configurable. But once we got there, we went from a handful of pilot airports to 12+ live across 3 continents.

Photo: Presentation setting or team photo

At Sea

Duty-free doesn't only happen in airports. Cruise ships operate under the same tax exemptions, but with completely different constraints: satellite connectivity (expensive and intermittent), product catalogues tied to a specific voyage rather than a fixed location, pricing and even currencies that changes as the ship crosses borders.

When we partnered with Starboard Cruise Services, the core technology carried over directly. The adaptations we made followed the same principles of abstraction and configuration, making the platform cruise-agnostic the same way it had become retailer-agnostic for airports.

This allowed us to deploy proofs of concept for 8 cruise lines in a short timeframe, confirming that the architecture I had designed for airports translated well beyond them.

An industry first: Johnnie Walker boutique

A fully branded Johnnie Walker boutique within the Inflyter marketplace. Customers could explore collections, discover whiskies by flavour profile, and learn about the brand before purchasing for airport collection. This set the template for all future branded boutiques on the platform.

Johnnie Walker branded boutique homepage showing whisky bestsellers, travel retail exclusives, and product categories on the Inflyter marketplace.
Travel Retail Exclusives category page with product grid showing Johnnie Walker Ghost & Rare and Blue The Casks Edition.
Whisky flavour discovery feature filtering by smoky profile, showing Johnnie Walker Island Green and Lagavulin recommendations.
The Johnnie Walker Story brand page with heritage content and historical imagery integrated into the boutique experience.
Johnnie Walker Highball cocktail guide with recipe steps and mixer suggestions within the branded boutique.