Compare the monthly cost of geocoding from the edge (R2 and Workers), from one Hetzner server, from AWS and from hosted vendors. Every price links to the vendor page it came from. Search on R2 alone (the .glx file) was measured too slow for new queries, so the edge row is a Worker result cache in front of one Hetzner server. For map tile hosting cost, see the tileserver-rs calculator.
OptionBilling basisMonthly costLatency from Singapore
Edge
Cloudflare Workers result cache + Hetzner AX102
A Worker answers repeated queries from the Cloudflare cache; new queries go to the Hetzner server.
Monthly cost $309.00
+ $149.00 one-time setup
Latency Repeated query: ≤ 50 ms to the nearest Cloudflare location, plus 6 ms in the Worker (measured). New query: the Hetzner trip, 157 ms to Germany (ping), plus the query time.
A .glx index on R2; a Worker reads index ranges. No server.
Monthly cost Not viable
Latency ≤ 50 ms to the nearest Cloudflare location for 95% of users (source). R2 reads that miss the cache add the trip to the bucket region.
Measured on the full planet (6 Oct 2026, 54.6 GB file, 199 new queries from India): median 1,974 ms, 23% within 1 s and 51% within 2 s. Each uncached R2 read takes about 350 ms, and a new query needs 3 or more rounds of reads. The file costs about $0.82 a month on R2, but it is too slow without a server. Repeated queries were fast (22 ms), so the result cache below keeps that part.
The .glx index split: dictionary, records and start-up data in SQLite-backed Durable Objects (about 100 shards for the planet), posting lists in R2. A searcher object reads them by RPC. No server. Sizes scaled from the France file.
Monthly cost $197.58
Latency New query, measured from India on France: 174 ms median, 898 ms for 95%, 96.3% within 1 s. Queries that read a posting list from R2 (about a third) take longer. The objects run in one region (Asia-Pacific); users far from it add the trip to it.