SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
3 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
7.9 KB

# osm-overpass — OpenStreetMap data centers via the Overpass API

id / implementation osm-overpass (apps/worker/src/connectors/datasets/osm-overpass.ts)
kind / mode / priority community / dataset / 3
endpoints primary https://overpass-api.de/api/interpreter, fallback https://overpass.private.coffee/api/interpreter (kumi.systems replied 504 after 204 s during verification; maps.mail.ru is another working public instance)
entities NormalizedFacility, key osm:<type>/<id> (e.g. osm:way/123), externalIds.osm
schedule dataset: monthly
requests per run one Overpass query per world tile (13 tiles, params.maxBboxesPerRun), sequential, ≥ 10 s apart
license ODbL 1.0 — © OpenStreetMap contributors (attribution mandatory)
attribution "© OpenStreetMap contributors, ODbL 1.0" — must be displayed wherever OSM-derived facts are shown; derived databases are share-alike

# License (verified 2026-09-11)

https://www.openstreetmap.org/copyright:

"OpenStreetMap is open data, licensed under the Open Data Commons Open Database License (ODbL) by the OpenStreetMap Foundation (OSMF). In summary: You are free to copy, distribute, transmit and adapt our data, as long as you credit OpenStreetMap and its contributors. If you alter or build upon our data, you may distribute the result only under the same license. […] Where you use OpenStreetMap data, you are required to do the following two things: Provide credit to OpenStreetMap by displaying our attribution notice. Make clear that the data is available under the Open Database License."

Implication for DataCenterIndex: facts sourced from OSM keep their provenance.sourceId so the UI/API can show "© OpenStreetMap contributors" next to them and the export layer can honour share-alike for OSM-derived subsets.

# Access policy — why respectRobots: false

https://overpass-api.de/robots.txt disallows /api/ for User-agent: * (aimed at search-engine crawlers). The Overpass API is a query service whose terms of use are the "Commons" guidance (https://dev.overpass-api.de/overpass-doc/en/preface/commons.html, retrieved 2026-09-11):

"As a broad guideline to stay within safety margins, users are expected to send a maximum of about 10000 requests per day and keep their download volume below about 1 GB per day." — problematic behaviours listed: sending the same request tens of thousands of times a day, fetching elements one by one millions of times, "Stiching bounding boxes to scrape the full data of the complete world", using the public instance as an app backend.

We send ≈ 13 requests and ≈ 3 MB per monthly pass with the bot UA, sequentially, honouring load shedding (429/504 → backoff, fallback, resumable cursor). overpass.kumi.systems has no robots.txt (404). Decision to confirm by the owner: fetch.respectRobots: false in the YAML applies to this API host only.

# Query

text
[out:json][timeout:180][maxsize:536870912];
( nwr["telecom"="data_center"](S,W,N,E); nwr["building"="data_center"](S,W,N,E); );
out center tags;

Tiles (a partition of lat −60…85, shared edges, no overlap): na-west, na-east, atlantic-north, latam, eu-west, eu-east, africa-west, africa-east, mena, central-asia, south-asia, east-asia, sea-oceania (see WORLD_BBOXES). The connector keeps a cursor (osm-overpass:cursor in connector state) advanced after each successfully extracted tile, so an interrupted run resumes at the failed tile and params.maxBboxesPerRun can spread a full pass over several runs (dry runs never write state).

Fetch policy: primary → fallback → primary (params.maxAttempts, default 3), backoff params.backoffMs × attempt between attempts, only for load-shedding signals (timeout/connection, 429, 502, 503, 504). A tile that still fails is logged and its cursor is not advanced.

# Tag mapping (never invents)

field tags
name name → name:en; if absent, operator (+ ref, e.g. "Equinix LD4"). Features with neither name nor operator are skipped
aliases name:en (when different), alt_name, short_name, official_name, old_name, brand, operator:short
operatorName / ownerName operator → brand / owner
address addr:housenumber + addr:street (number first for US/CA/GB/IE/AU/NZ/FR/IN/ZA/SG/HK/MY/PH or when country unknown), else addr:street or addr:housename
city, regionName, postalCode addr:city, addr:state/addr:province, addr:postcode
countryIso2 addr:country only when it is an ISO-2 code (present on ~8 % of features). Otherwise null: ingest must resolve the country from the coordinates / metro
geo node lat/lon, or center of ways/relations → precision exact, source community:osm
openedOn start_date → opening_date via parsePartialDate; years < 1950 dropped (that is the building's date, not the DC's)
totalPowerMw only data_center:power and only if it says MW (parseMw), e.g. "16 MW", "77.4MW". power=* is never used (it is the OSM power-infrastructure key)
status operational by default (OSM maps existing features); construction=*/building=construction → under_construction; disused/abandoned → closed
facilityType inferFacilityType(name + description + operator) or null (not defaulted to colocation)
website website → contact:website → url (http(s) only)
externalIds osm: "way/123", wikidata: Q…, operator_wikidata: Q…, osm_ref
facts totalPowerMw (osm-tag:data_center:power), openedOn (osm-tag:start_date)

# Verified live (2026-09-11)

text
node node_modules/tsx/dist/cli.mjs scripts/try-connector.ts config/connectors/osm-overpass.yaml --limit 3 --json /tmp/osm-overpass.json
tile na-west        :   563 features →   472 kept ( 91 without name/operator), 6.0 s
tile na-east        : 1 337 features → 1 053 kept (284 without name/operator), 13.9 s
tile atlantic-north :    25 features →    22 kept (  3 without name/operator), 0.8 s
TOTAL 1 547 entities, 1 547 valid, 0 rejected, 0 warnings, 25 s (10 s pacing included)

Coverage of the 1 547: all have coordinates (exact), 1 225 an operator, 929 an address, 410 a website, 44 an opening date, 37 an addr:country; status 1 539 operational / 8 under_construction; no data_center:power in MW in these tiles (Europe has a few: "1.2 MW", "16 MW", "77.4MW"). A first --limit 2 run met a 504 on na-east (load shedding) and the then-fallback kumi.systems timed out — hence the alternating retry sequence and the fallback change. An exploratory Europe query (35,-12,72,40) returned 1 786 features in 38 s / 632 kB, 275 without name/operator — a full world pass should yield roughly 4 000–6 000 facilities. Samples: osm:node/3732415309 "The Pittock Internet Exchange" (Portland OR, operator Alco Properties, internet_exchange), osm:node/1825907839 "Southwest Cyberport" (Albuquerque, alias SWCP, website).

# Quirks / gaps

  • No addr:country on most features → countryIso2 null with a validation warning only when coordinates are also missing (never the case for Overpass out center). The ingest/reconcile step must derive the country from coordinates.
  • Overpass load shedding is real (504 on the second tile during verification; "Rate limit: 2" slots per IP). Keep minDelayMs ≥ 10 s, do not parallelise, keep maxBboxesPerRun small if runs are frequent.
  • Public mirrors are volunteer-run and fluctuate (kumi.systems 504 after 204 s, private.coffee 21 s for a tiny query, maps.mail.ru 2 s but no robots.txt/terms page); the connector alternates primary/fallback instead of depending on any single one. overpass.osm.ch is Switzerland-only — unusable.
  • OSM also has office=telecommunication, man_made=data_center (rare) and telecom=exchange — not queried (precision over recall).
  • Multiple OSM features can represent one facility (building way + node POI). They get distinct keys; reconciliation (same name/operator within 250 m) merges them.