Skip to content

A booking platform tuned from search to checkout

A reservation platform where the search-to-checkout path is designed around real traveler behavior, then engineered to load fast and hold up under seasonal spikes.

Wayloft
USD · $ Help My tripsDW
Where to next?

Flights and stays, showing only what you can still book for your dates.

Flights Stays Flight + StayRound trip
FromSan Francisco (SFO)All airports nearby
ToLisbon (LIS)Portugal
DatesOct 22 – Oct 31Thu, Oct 22 → Sat, Oct 31
Travelers2 adults · 1 roomEconomy
Search
Bookable for your dates only Add a stay in LisbonPrices in USD
Pick up where you left offPopular from San Francisco
SFO → LIS + Hotel Azulejo AltoOct 22 – Oct 31 · 2 adults
Saved at step 1 of 3 · Seats & extrasSeats 14A, 14B chosen · 2 checked bags/checkout/WL-7K4QMR?step=seats
$1,686.80Resume checkout
LisbonPortugal · Oct 22 – Oct 31Round trip from $760.40
ReykjavíkIceland · Nov 5 – Nov 12Round trip from $689.90
Mexico CityMexico · Oct 29 – Nov 3Round trip from $412.30
TokyoJapan · Nov 14 – Nov 24Round trip from $1,082.60
Results list only what is still bookable Back and refresh keep your checkout where you left it Change seats, bags and dates on your trip yourself

What the engagement involved

Industry

Travel & Tourism

Duration

16 weeks

Cooperation model

Fixed price, phased

Services
UX researchFrontend engineeringCheckout redesign
Integrations
Amadeus GDSSkyscannerSendGridSegment
Technologies
Next.jsTypeScriptTailwind CSSGraphQLRedisStripe API
Team
1 Project lead1 Product designer2 Frontend engineers1 Backend engineer1 QA engineer

Client name withheld under NDA. Engagement details are shown to the extent our agreement permits.

Introduction

What we were brought in to do

The booking flow converted well on desktop and lost travelers on mobile. We reshaped the whole journey (search, results, property detail and checkout) around how people actually decide, then rebuilt it as a fast, responsive web app.

Two-thirds of traffic was already mobile and converting at less than half the desktop rate, which the team had been treating as a design problem for three quarters. The engagement started six months before the summer booking window, which set both the deadline and the load target: whatever shipped had to survive ten times normal traffic on the first attempt.

Design & Build

The problem

Where the old way broke

  1. 01

    The previous flow buried key decisions and dropped users between search and payment. Pages were slow on mobile, and checkout asked for too much too early, which drove a 62% abandonment rate during peak travel season.

    The single-page checkout asked for passport details before showing a total, and the abandonment analytics put 62% of the loss on that one screen. Underneath, search re-queried the origin on every filter change, so a traveler narrowing by price on a hotel connection waited four seconds per checkbox and usually gave up narrowing.

    We restructured the booking platform around a clear search-to-confirm path, split checkout into staged steps, and rebuilt the frontend for fast rendering and stable performance during peak booking windows.

Instant Filter Engine

Sub-50ms search filtering across 10,000+ real-time inventory listings with edge-cached queries.

Filtering used to round-trip to the origin on every checkbox. Now the inventory index ships to the edge as a compact binary payload and the filter runs in the browser against it, falling back to a GraphQL query only where live pricing is needed. Redis holds that pricing layer on a short TTL, so a room that sold out three seconds ago disappears from the list before anyone can fail at checkout on it.

What shipped
  • Compact inventory index served from the edge
  • Client-side filtering; server called only for live price
  • Short-TTL pricing so sold-out stock drops out fast
Wayloft
USD · $ Help My tripsDW
Lisbon Fri, Oct 23 – Sat, Oct 31 · 8 nights 2 guests · 1 roomUpdateSort: Recommended

Filters

Clear all
Bookable for your datesAlways on. Sold-out rooms drop out.
Price per night$80 – $200
Before taxes & fees
Neighborhood
Alfama9Chiado7Graça5Príncipe Real6Estrela11Belém0
Options
Free cancellation Breakfast included Pay at the property
Guest rating
Any8+9+
38 bookable staysFiltered on this device · under 50 ms3 sold out since you searched · removedIndex of 10,000+ listings
Hotel Azulejo AltoSaved Alfama, Lisbon9.11,284 reviewsFree cancellation
$168 / night8 nights $1,344.00 + $174.72 taxes$1,518.72 total Price checked live
Casa Travessa Chiado, Lisbon8.8942 reviewsFree cancellation
$142 / night8 nights $1,136.00 + $147.68 taxes$1,283.68 total Price checked live
Miradouro Rooms Graça, Lisbon8.6611 reviewsNon-refundable rate
$121 / night8 nights $968.00 + $125.84 taxes$1,093.84 total Price checked live
Pátio das Laranjas Príncipe Real, Lisbon9.3457 reviewsFree cancellation
$189 / night8 nights $1,512.00 + $196.56 taxes$1,708.56 total Price checked live
Estrela Garden House Estrela, Lisbon8.9733 reviewsFree cancellation
$156 / night8 nights $1,248.00 + $162.24 taxes$1,410.24 total Price checked live
On screen

Search results filtered down to what's actually bookable: 38 Lisbon stays for eight nights, filtered on the device in under 50 ms against an index of 10,000+ listings, three stays that sold out after the search already removed, and every total priced with taxes.

Wayloft
USD · $ Help My tripsDW
1Seats & extras2Travelers3Payment/checkout/WL-7K4QMR?step=seats· back & refresh keep this step

Choose seats

2 travelers · pick 2 seats per flight
AL 318 · SFO → LIS · Thu, Oct 22· 14A, 14B AL 319 · LIS → SFO · Sat, Oct 31· Not chosen
Exit $64.00Preferred $38.00Standard · Included
ABCDEF
B10EF
ABC11DE
A12DEF
ABC13
C14EF
B15DEF
BC16DF
AC17DE
C18DEF
ABC19E
AB20DF
BC21DE
AC22EF
AB23DF
BC24DE
AC25EF
Your seats Paid seat Included TakenFront of cabin ←

Bags · still step 1

Per traveler, both flights
2 of 2Personal itemFits under the seatIncluded
2 of 2Carry-on bagOverhead bin, up to 22 lbIncluded
2 addedChecked bagUp to 50 lb$45.00 each

Your trip

Ref WL-7K4QMR
SFO → LIS · Thu, Oct 22Alcyon Air AL 318 · 9:40 PM – 4:50 PM · 11h 10m nonstop
LIS → SFO · Sat, Oct 31Alcyon Air AL 319 · 11:15 AM – 4:20 PM · 12h 05m nonstop
2 adults · Economy · Round trip
Base fare2 × $612.00$1,224.00
Taxes & carrier fees2 × $148.40$296.80
Seats 14A, 14B · Preferred2 × $38.00 · outbound$76.00
Checked bags2 × $45.00$90.00
Total so farFare $1,520.80 + extras $166.00$1,686.80
Seats 14A and 14B held for youFare re-checked against live pricing before you pay14:32
Traveler and passport details come next, after you have seen this total. Currency is confirmed from your billing address at payment.Continue to travelers

Staged 3-Step Checkout

On screen

Seat selection and the staged checkout: step 1 of 3 held in the URL, seats 14A and 14B held on the outbound flight, two checked bags, and a fare breakdown that sums to $1,686.80 before any passport details are asked for.

A lean checkout flow with inline validation, currency auto-detection and one-tap mobile payments.

One long form became three steps that each hold their state in the URL, so the back button behaves and a half-finished booking survives a refresh. Inline validation runs against the same schema the API enforces, which removed the whole class of failure where the form accepted a value the server then rejected. Currency is resolved once from the billing address, never guessed from the IP.

What shipped
  • Step state in the URL: back and refresh are both safe
  • One validation schema shared by client and API
  • Currency from the billing address, never guessed from the IP

Seasonal Peak Resilience

Resilient edge architecture built to withstand 10x traffic spikes during holiday booking windows.

Peak weeks put ten times normal load on the same infrastructure. Search and browse were made fully static-renderable so they serve from cache under any load, leaving checkout as the only path that touches origin. Checkout sits behind a queue that admits a fixed rate, so it never accepts everything and then times out. The whole route was load-tested at twelve times peak before the first holiday window.

What shipped
  • Search and browse served entirely from cache
  • Rate-admitting queue in front of checkout
  • Load-tested at 12x ahead of the first peak
Overview

Booking windows open · search and browse served from cache, checkout behind the queue

LiveToday JM
Booking conversion
+34%8 weeks vs the same 8 last year
Mobile checkout completion
+41%Since the staged checkout launched
Median page load
1.2sField data, weighted to the traffic mix
Checkout load test
12× peak50,000 concurrent · 0 server errors

Revenue by hour

Today Same weekday last year
12a3a6a9a12p3p

Page load & serving

Field sessions
1.2s median
Median page load, all sessions, today
Search & resultsEdge cacheProperty pagesEdge cacheFilteringIn the browserCheckoutOrigin, via queue

Live booking stream

Peak windows plan for 10× normal traffic
TimeReferenceBookingDeviceAmountStatus
2:14:08 PMWL-7K4QMRSFO → LIS · 2 adults Mobile$1,686.80Confirmed
2:14:08 PMWL-7K4QMSHotel Azulejo Alto · Tiled Balcony King Mobile$1,771.84Confirmed
2:14:05 PM—Hotel Azulejo Alto · Garden Twin Desktop—Sold out · removed
2:14:01 PMWL-7K4QJ2JFK → KEF · 1 adult Mobile$584.20In checkout queue
2:13:57 PMWL-7K4QHXCasa Travessa · Chiado Double Desktop$1,283.68Confirmed
2:13:52 PMWL-7K4QHBORD → MEX · 3 adults Mobile$1,397.10Seats held · step 2
2:13:46 PMWL-7K4QGTMiradouro Rooms · Twin Mobile$1,093.84Confirmed
2:13:40 PMWL-7K4QG4SEA → HND · 2 adults Desktop$2,276.50Confirmed
On screen

The operations console: +34% booking conversion, +41% mobile checkout completion and a 1.2s median page load, revenue by hour against last year, which routes serve from cache and which reach origin through the queue, and the live booking stream.

What we built together

  1. 01

    Mapped the real decision path from 40+ recorded booking sessions

    Sessions were coded for where a traveler hesitated, not only where they dropped, and that put the fault a screen earlier than the analytics did.

  2. 02

    Prototyped a staged checkout and tested it with returning travelers

    Testing with returning travelers was deliberate. They know what the old flow asked for, so any hesitation means the step order is wrong.

  3. 03

    Rebuilt the frontend for sub-second navigation between steps

    The inventory index moved to the edge and the filter runs in the browser against it, calling the server only where live pricing genuinely changes the answer.

  4. 04

    Load-tested the checkout against projected seasonal peaks

    Checkout was load-tested at twelve times peak before the first holiday window, which is where the rate-admitting queue came from.

Outcome

Operational results after launch

+34%

Booking conversion

+41%

Mobile checkout completion

1.2s

Median page load

Conversion compares the eight weeks after launch against the same eight weeks the previous year, so the seasonal shape is held constant and nothing is flattered by a quiet spring. Median page load is field data from real sessions weighted to the traffic mix, with no lab runs.

Client name withheld under NDA. Figures are approximate, drawn from the engagement’s own reporting.

Process

Phase by phase

  1. Phase 1: Discovery & UX Audit

    User Journey & Friction Analysis

    Audited 40+ recorded booking sessions and analytics to isolate mobile drop-off triggers and cart abandonment spikes.

    • Friction Audit Report
    • User Journey Map
    • Mobile Conversion Benchmark
  2. Phase 2: UI/UX Redesign

    Staged Mobile-First Architecture

    Designed a progressive 3-step checkout with instant price breakdown, inline field validation, and 1-tap mobile payment options.

    • Figma Prototype System
    • Component Design Library
    • Usability Test Results
  3. Phase 3: Core Engineering

    High-Performance Next.js Build

    Rebuilt the frontend on the Next.js App Router, with edge Redis caching for search queries and optimistic state handling for zero lag.

    • Next.js App Engine
    • GraphQL API Integration
    • Edge Cache Strategy
  4. Phase 4: Load Testing & Go-Live

    Peak Stress Simulation & Release

    Executed load tests simulating 50,000 peak concurrent booking requests, achieving zero server errors and 1.2s median page load times.

    • k6 Load Testing Suite
    • Production Deployment
    • Performance Baseline Monitoring
  5. Instant Filter Engine

    Instant Filter Engine

    Sub-50ms search filtering across 10,000+ real-time inventory listings with edge-cached queries.

Wayloft
USD · $ Help My tripsDW
Stays Lisbon Alfama
Hotel Azulejo Alto
9.11,284 reviews Rua dos Remédios, Alfama Wi-Fi Breakfast available
Savedfrom $168 / night
+ 24 photos
Room typesFri, Oct 23 – Sat, Oct 31 · 8 nights · 2 guests · priced for your whole stayGarden Twin sold out 3 seconds ago · removed
Courtyard DoubleRoom type 1 of 3
1 double bed · 18 m² Inner courtyard Free cancellation until Tue, Oct 20
$168.00 × 8 nights$1,344.00
Taxes & fees (13%)$174.72
Total for your stay$1,518.72
4 rooms left for these datesChoose this room
Tiled Balcony KingRoom type 2 of 3Your room
1 king bed · 24 m² Rooftops, balcony Free cancellation until Tue, Oct 20
$196.00 × 8 nights$1,568.00
Taxes & fees (13%)$203.84
Total for your stay$1,771.84
2 rooms left for these dates Selected
River SuiteRoom type 3 of 3
1 king bed + sofa · 36 m² Tagus river Free cancellation until Tue, Oct 20
$254.00 × 8 nights$2,032.00
Taxes & fees (13%)$264.16
Total for your stay$2,296.16
1 room left for these datesChoose this room
On screen

A property page where the room types are priced side by side for the whole eight-night stay, nightly rate, taxes and total, with the room that sold out three seconds ago already gone from the list.

Ways of working

About our collaboration

  • A cross-functional team of 5 worked on a fixed price, phased basis over 16 weeks, covering UX research, Frontend engineering, Checkout redesign. We held a standing mid-week checkpoint and wrote decisions down in place of status meetings. Nothing shipped without a live demo first.

    Forty recorded sessions came before any design work, and the staged checkout was prototyped and tested with returning travelers before it was built. Load testing ran continuously from week six, never saved for a pre-launch gate, and that's why the queue in front of checkout exists at all. It was the answer to a failure found in week seven.

What we'd carry into the next one

03
  1. 01

    Staging mobile checkout into clear, bite-sized steps reduced cart abandonment by 41%.

    Abandonment fell because the steps each hold their state in the URL: a traveller who backs out to check something returns to a form that still holds their answers.

  2. 02

    Edge caching popular destination searches dropped global median page load time to 1.2s.

    Caching the searches people actually run beat caching everything. The long tail was never the load problem, and treating it as one had been wasting cache space.

  3. 03

    Optimistic UI updates ensured users never felt lag during inventory booking surges.

    Optimistic updates only work when the pessimistic case is honest. The short pricing TTL is what lets the interface move immediately without ever promising a sold-out room.

Three steps, one running total

The total comes before the passport

One round trip for two, from seats to a confirmed booking. Each stage shows what the traveler is asked, what's held for them, the address the stage lives at, and a total that's always its lines added up. Switch tabs, or use the arrow keys once one is focused.

Step 1 of 3 · Seats & extras /checkout/WL-7K4QMR?step=seats
Asked at this stage
Two seats on the seat map. Nothing personal yet.
Why it behaves this way
The fare is read from the short-TTL pricing layer, so a seat or fare that has just gone is never offered.
Held right now
  • Seats 14A and 14B on AL 318, held for you · 15:00 hold (illustrative)
Refresh or press back here and the same URL brings the traveler to this stage with these answers.
SFO → LIS round trip · 2 adults · USD
  • Base fare2 × $612.00$1,224.00
  • Taxes & carrier fees2 × $148.40$296.80
  • Seats 14A, 14Badded2 × $38.00 · Preferred$76.00
Total so far$1,596.80
$1,224.00 + $296.80 + $76.00
Architecture

From a traveler’s first filter to a confirmed booking on their phone

Everything a traveler browses is served from cache or computed in their browser. Only checkout reaches origin, and it goes through a queue whose rate was found by load testing, never assumed.

  1. 01 · Trigger
    Search & filter in the browserThe inventory index ships to the edge as a compact binary payload and filtering runs against it on the device: under 50 ms across 10,000+ listings, with no round trip per checkbox.
  2. 02 · Queue
    Rate-admitting checkout queueCheckout is the only path that touches origin, and a queue admits it at a fixed rate instead of accepting everything and timing out under 10× normal traffic.
  3. 03 · Engine
    GraphQL pricing + staged checkoutThe server is called only where live price changes the answer. One validation schema is shared by the form and the API, so nothing the form accepts is rejected later.
  4. 04 · State
    Redis pricing TTL + step state in the URLPricing lives on a short TTL, so a room that sold out seconds ago drops out of the list. Each checkout step holds its state in the URL, so back and refresh are safe.
  5. 05 · Delivery
    Static search & browse from cacheSearch and browse are fully static-renderable and serve from cache under any load; 1.2s median page load in field data. Checkout load-tested at 12× peak: 50,000 concurrent requests, zero server errors.

So a booking is a booking

Real inventory, a checkout that finishes, pages that stay fast

Gone stock is never offered

Live pricing sits in Redis on a short TTL, so a room that sold out seconds ago disappears from results before it can fail at checkout. The form validates against the same schema the API enforces, so the server never rejects what the traveler was allowed to submit.

No checkout left hanging mid-payment

Checkout sits behind a queue that admits a fixed rate instead of accepting everything and timing out. It was load-tested at 12× peak before the first holiday window: 50,000 concurrent booking requests, zero server errors. Step state lives in the URL, so a refresh returns to the same step of the same booking.

Slow pages no longer cost the mobile buyer

Search and browse serve entirely from cache under any load, and filters run in the browser in under 50 ms where each checkbox used to wait four seconds. Median page load is 1.2s, measured from real sessions weighted to the traffic mix.

Are travelers leaving somewhere between search and payment? Scope your build in 3 minutes.

Scope your build
Have a project?

Let's talk

Running a large platform, shaping a first MVP, or getting a product ready for a funding round? Tell us where you are. We'll shape the process around it, and stay with you after launch.