Info

Reward Seat Finder

Why I built it

Finding reward flights on Qantas and Velocity is slow. I wanted a fast, utilitarian tool to scrape availability directly and bypass clunky airline interfaces. It’s built for speed and utility, not as a marketing site.

The app uses a brutalist, high-contrast aesthetic. Pure data, no fluff.

How it’s structured

The stack is a Next.js 14 frontend backed by PostgreSQL (Prisma) and Redis. The heavy lifting happens in a separate Node.js worker running Playwright and Chromium.

I deployed it on AWS using Terraform. It runs on a Graviton2 (ARM64) t4g.small instance. The 2GB of RAM is crucial because scraping with headless browsers easily OOMs smaller instances like the t3.micro. CI/CD pushes multi-platform Docker images to ECR, and Docker Compose handles orchestration on the box via AWS SSM.

The hard parts

Scraping airlines headless means fighting anti-bot systems and transient network drops.

For Velocity, I had to manage transient Chromium timeouts, guard page.evaluate calls against SPA navigations, and strictly manage browser user-agents to prevent Imperva blocks. For Qantas, I built a region-mode fanout that respects rate limits by serializing source calls. When Qantas started throwing 403s on broad month-view lookups, I had to write fallback logic to pivot into single-page, day-by-day probes to maintain data coverage.

What’s next

Right now, live scraping is stable. The next step is expanding the background worker to handle automated saved searches and email alerts.


← Back to projects