Cross-system data product
Car Rental Price Index: a public price benchmark across five systems
A public website that tells travellers whether a car hire quote is fair, built from a price archive the client had been collecting for years, without moving it anywhere.
- Role
- Architect and developer
- Client
- Car Rental Price Index
- Period
- 2023–2026
The problem
Car hire quotes vary wildly by airport, month and how far ahead you book, and there is no reference price to judge a quote against. The product answers one question for a traveller: is the price I've been quoted fair for this airport? It then hands off to the booking provider. The site's job is the judgement before the booking.
What already existed
- A C# console collector that had been pricing the same pickup dates month after month through the CarTrawler OTA XML API since November 2023.
- A SQL Server archive on Windows Server holding those prices: over 30 million rows across 395 airports and more than 240 rental companies.
The obvious move was to lift everything into a cloud warehouse and rebuild the collector. Neither was necessary. The collector worked. SQL Server was fine for a monthly batch. BigQuery was considered and rejected.
What I built, and what I deliberately didn't
Built: the systems around the archive that turn raw prices into a public, fast, cheap-to-run site.
- A Python pipeline that reads the archive, computes medians and quartiles per airport, country and globally (with minimum sample sizes, so thin data is never presented as a benchmark), and publishes JSON artefacts to a private Vercel Blob store.
- A Next.js site that reads only from those artefacts. Pages are statically generated per locale, country and airport, with cache tags revalidated when a new batch lands. Nothing on Vercel ever touches the database.
- A nightly Vercel Workflow that prices one reference trip per airport (a few airports at a time), stores the live figure beside the archive figure and revalidates that airport's page. A monthly workflow prices 3-, 5- and 7-day hires to show how duration changes the rate.
- A live price check: the one request-time path that calls the booking API, with the airport resolved server-side, market and currency taken from the locale, and a per-IP rate limit.
- An AI writer for the per-airport guidance paragraphs, using the Vercel AI SDK through the AI Gateway. Every figure in the generated text has to exist in the data (a code-level "numbers gate"), a detector rejects generic AI phrasing, and there is a templated fallback when a draft fails.
Didn't build:
- A new collector or a cloud warehouse. The C# tool and SQL Server stayed.
- A database behind the website. Static artefacts and a small blob store are cheaper, faster and have nothing to go down.
- An AI feature anywhere a template would do. The model writes prose; the numbers come from SQL.
For the technical readerUnder the hood: production details, architecture and stack
Production details
- Retries and isolation: rate-limit responses back off and retry; permanent errors don't. Each airport is processed independently, so one failure never stops a run, and a failed fetch is never reported as "no data".
- Reproducible builds: each site build is pinned to a batch date. Manifest writes are atomic and partial runs merge rather than wipe.
- Cost control: output tokens are capped, unchanged airports skip the writer, and a single fleet manifest avoids millions of small blob reads a month.
- Testing: unit tests across the web and pipeline code, plus integration tests run against the live archive.
- Multi-currency and locale: figures are stored in GBP and converted on the client with daily ECB rates, labelled as indicative. Two locales ship with hreflang in the sitemap.
- Search: airports under the sample floor are noindexed and left out of the sitemap; sitemaps are submitted to search engines automatically after each batch.
- Built for AI assistants as well as search: the site is designed to be read and cited by LLM-based assistants, not only ranked by Google: a plain-text
llms.txtsummary, browser-agent tools exposed through WebMCP so an agent can query the index directly, server-side capture of crawler and AI-assistant traffic so that audience can be measured, and IndexNow pings so fresh batches are picked up quickly.
Architecture
- C# collectorMonthly batch, OTA XML API
- SQL Server30M+ prices, Windows Server
- Python pipelineMedians, quartiles, artefacts
- Vercel BlobJSON per airport / country
- Next.js siteStatic pages, nightly workflow, live check
Stack
C#, SQL Server, Python, Next.js, TypeScript, Vercel Workflow, Vercel Blob, Vercel AI SDK.