rizalfarhan.dev
Direct BookingNext.jsGoPostgreSQL

Villa Website Platform

3.2% direct booking conversion — bypassing $93K/year in OTA commission fees

$93K

OTA commissions bypassed/year

3.2%

Direct booking conversion

35K+

Monthly organic visitors

Business Context

Luxury villa operators in Bali pay 15–18% OTA commission on every booking routed through Airbnb or Booking.com. For a portfolio generating significant nightly revenue, that's roughly $93,000/year in fees — money that could stay with the operator if guests booked direct.

The business needed a multi-property direct booking platform that matched OTA-quality discovery UX while delivering faster checkout, better SEO, and real-time availability synced from the central PMS.

The Challenge

The previous WordPress-based site achieved only 0.8% direct conversion. Pain points:

  • 4.2s LCP on image-heavy villa pages — mobile guests bounced before seeing availability
  • Availability checks hit a slow PHP backend — 800ms+ API responses made the booking widget feel broken
  • No SSG — every page request rebuilt dynamically, hurting SEO crawl efficiency
  • OTA dependency — no compelling reason for guests to book direct beyond a small discount

Growing direct bookings required a platform that felt faster and more trustworthy than clicking through to an OTA listing.

Architecture Decision

Chosen: Next.js 14 (App Router) with SSG/ISR for villa pages, Go (Fiber) backend for booking API, PostgreSQL for reservations, deployed on Vercel + containerized Go service.

Rejected: Full Next.js API routes for booking logic — rejected because the booking engine needed sub-100ms responses under concurrent availability checks during peak season, and Go's concurrency model outperformed Node for this specific hot path.

Why SSG + ISR: 80+ villa pages pre-render at build time with nightly revalidation. Property content (photos, descriptions, amenities) changes infrequently — serving static HTML from the edge cut LCP from 4.2s to 1.1s.

Why Go for booking API: Availability queries involve date-range scans across multiple units with lock checks against the PMS. Go/Fiber handles concurrent requests with minimal memory overhead — p99 response times dropped from 800ms to under 120ms.

Key Results

MetricBeforeAfter
Direct booking conversion0.8%3.2%
OTA commission costs~$93K/year (15–18% per booking)Reduced via direct channel growth
Page load (LCP)4.2s (WordPress)1.1s (SSG + CDN)
Booking API response time800ms+ (PHP monolith)Under 120ms (Go/Fiber)

Lessons

  • Direct booking growth is a performance problem before it's a marketing problem — guests abandon slow villa pages regardless of photography quality.
  • SSG for property pages + dynamic API for availability is the right split; pre-rendering 80+ villa pages nightly beats on-demand rendering at this catalog size.

Next Project

VIPApp96% faster compliance reporting — 2 days/month → 2 hours/month