Where this stands
Two findings are already firm. The third — the one the decision actually turns on — needs another few weeks of collection.
What we know
Cooling carries an 80% premium
Baan Padel charges ฿1,800; the padel co. charges ฿1,000 and sits 1.8 km away in the same catchment. Same residents, same commute, double the price. That is as close to a controlled test of what Bangkok pays for air conditioning as this market offers.
The top-ranked site is 740 m from the incumbent
Rama IV east ranked joint-first on rent and ceiling height, but it is 740 m from Baan Padel — the one operator already proving the model. That is opening opposite the market leader, not filling a gap. Ari / Lat Phrao is 5.62 km from any court and is the only genuinely isolated candidate.
Fill rate is still unknown
Break-even lands near 20% under central assumptions, but drop fill to 28% with realistic cooling costs and payback stretches from 2.4 years to 14.6. The decision is barely sensitive to rent or build cost and almost entirely sensitive to this one number — which nobody publishes.
How to read this dashboard. Anything under Market and Location is measured from live booking data. Demand is deliberately empty until the collector has history. Economics is your assumptions, not evidence. Method covers how the data is gathered and where it is weak.
The measured market
Five venues publish a machine-readable calendar. Court counts, prices and opening hours are read directly from it every hour, not from listings.
| Venue | Zone | Cooling | Courts | Hours (BKK) | Rate / hour | Nearest rival |
|---|
Coverage
The live feed sees 19 of roughly 44 courts. Missing: Kross (4 branches, own booking app), Bangkok Padel (Matchi), Padel Asia, Patana and St Andrews 107 — about 57% of Bangkok's supply. None publishes a machine-readable calendar; Kross would need a browser-driven scraper.
They are also absent from the map. Coordinates could not be verified for any of them, and a dot that looks as precise as a measured one while being a guess is worse than no dot at all.
Where the courts are
Every venue plotted at its real coordinates. Circle area is proportional to court count. Drag to pan, scroll to zoom, click a marker for detail.
Distance to the nearest existing court
| Candidate zone | Nearest existing court | Distance | Read |
|---|---|---|---|
| Ari / Lat Phrao | Bel Club Padel | 5.62 km | Genuinely underserved |
| Punnawithi / Udom Suk | the padel co. | 2.09 km | Thin but open |
| Bearing | Sunshine Padel | 1.54 km | Contested |
| Rama IV east | Baan Padel (AC) | 0.74 km | Head-on with incumbent |
On distance alone the ranking in the original brief looks inverted. Rama IV east scored well on rent and ceiling height, but those are solvable problems; sitting 740 m from an established competitor with two years of pricing data is not.
Fill rate by hour
The number the business case turns on, and the one nobody publishes. The collector snapshots every court hourly and infers bookings from slots that vanish before their start time.
Deliberately empty. An earlier version of this grid showed a sample pattern. Fabricated cells that
look measured are worse than blank ones — they get quoted back as evidence months later. These
populate from fillrate.json once history exists. Useful signal needs about a week;
a stable weekday/weekend split needs four to six.
How a booking is detected
Each hour the collector records every bookable slot across an 8-day horizon. A slot that stops appearing well before its own start time was booked; one still listed on the final poll before it starts went unsold. Storing one row per slot rather than per snapshot keeps six weeks at roughly 50,000 rows instead of 18 million.
Known bias: slots booked before the collector ever saw them are invisible, so early fill rates read low. That resolves as history accumulates.
What fill rate do you actually need?
Until the Demand grid fills in, fill rate is the free variable. Move it and see what the club must achieve to cover its monthly costs.
Rate is blended across peak and off-peak — ฿1,800 is Baan's peak, not an all-day price. Opex is dominated by cooling 3,000 sqm in Bangkok. Assumes 16 hours/day × 30 days and court revenue only — no coaching, retail or F&B, which established clubs lean on heavily. Undiscounted, ignores ramp-up.
The sensitivity is the finding. Holding the rate steady and moving fill from 40% to 28% with realistic cooling costs pushes payback from 2.4 years to 14.6. Rent and build cost barely move it. That is why the collector exists.
How this is collected
Every figure under Market and Location comes from the same hourly pipeline. Here is what it does and where it is weak.
Pipeline
An hourly cron polls each venue's public booking calendar across an 8-day horizon and stores one row per slot, recording when it was first and last seen free. Prices, court counts, opening hours and coordinates are read from the same source.
The collector runs on a VPS in Singapore (~25 ms from Bangkok) and writes to SQLite.
Four traps this avoids
1. Times arrive in UTC, not Bangkok time. Read as local, every club appears to open at midnight.
2. Each club has its own booking-calendar horizon, and its far edge is indistinguishable from a sellout — Baan Padel returns zero courts 21 days out. Inferring demand from far-future dates manufactures fake 100% fill rates.
3. The documented API endpoint is dead. The published one is blocked by a WAF and returns 403 even from a real browser.
4. That same WAF blocks every datacenter IP. An identical request returns 200 from a Thai residential connection and 403 from a cloud host, so the collector exits through a residential proxy.
Known gaps
Slots booked before the collector first saw them are invisible, so early fill rates read low.
Roughly 57% of Bangkok's courts publish no machine-readable calendar and are not measured.
Candidate-zone positions are approximate district centres, good to about a kilometre.
The endpoint is undocumented and may change without notice — it already has once. The residential proxy is a paid dependency; if it lapses, collection stops quietly.