BG
EN
Tous les articles
#SIG#PostGIS#OpenStreetMap

Routes, bâtiments, points d'intérêt : un pays dans OpenStreetMap, ce sont des millions d'objets. Voici comment les servir en tuiles vectorielles directement depuis PostGIS, sans faire tomber le serveur.

Boris Gautier5 novembre 2026 3 min de lecture

Sur GeOsm, chaque pays a sa carte, construite à partir des données d'OpenStreetMap. Pour le Cameroun, cela représente plusieurs millions de bâtiments, de tronçons de route et de points d'intérêt. Envoyer ces données au navigateur en GeoJSON est hors de question : quelques kilomètres carrés de ville pèsent déjà plusieurs mégaoctets. La réponse standard est la tuile vectorielle.

Une tuile, c'est une requête

Le monde est découpé en tuiles indexées par un niveau de zoom z et des coordonnées x et y. Une tuile vectorielle (format MVT) contient la géométrie et les attributs des objets visibles dans ce carré, encodés de façon compacte et déjà projetés en coordonnées écran. C'est le navigateur, avec MapLibre par exemple, qui applique le style. Depuis PostGIS 3, la base sait produire ces tuiles toute seule : il suffit d'une requête par tuile.

tiles/roads.sql
-- $1 = z, $2 = x, $3 = y. Geometries are stored in EPSG:3857 (web mercator).
WITH bounds AS (
  SELECT ST_TileEnvelope($1, $2, $3) AS geom
),
features AS (
  SELECT
    ST_AsMVTGeom(r.geom, bounds.geom, 4096, 64, true) AS geom,
    r.osm_id, r.name, r.highway
  FROM roads r, bounds
  WHERE r.geom && bounds.geom                      -- uses the GiST index
    AND ($1 >= 13 OR r.highway IN ('motorway', 'trunk', 'primary', 'secondary'))
)
SELECT ST_AsMVT(features, 'roads', 4096, 'geom') FROM features;

ST_TileEnvelope calcule le carré de la tuile, ST_AsMVTGeom découpe et simplifie chaque géométrie à la résolution de la tuile (4 096 unités), avec une petite marge de 64 pour éviter les coutures entre tuiles, et ST_AsMVT assemble le tout en binaire. La condition sur highway est la plus importante : à petite échelle, on n'envoie que les grands axes.

Les quatre règles qui font la différence

  • Stocker les géométries directement en 3857 (ou garder une colonne précalculée) : transformer des millions de géométries à chaque tuile coûte cher.
  • Un index GiST sur la géométrie, et un filtre && sur l'emprise de la tuile : c'est lui qui transforme un parcours complet de la table en quelques millisecondes.
  • Un niveau de détail par zoom : pas de bâtiments sous le zoom 14, pas de chemins sous le 13, des géométries généralisées pour les petits zooms.
  • Des attributs choisis : envoyer seulement ce que le style et les fenêtres d'information utilisent, pas les 80 étiquettes OSM de chaque objet.

Le cache fait le reste

Les données OSM changent, mais pas à la seconde. Une tuile générée peut donc être gardée : en mémoire ou sur disque côté serveur, puis dans le cache du navigateur et du CDN grâce aux en-têtes HTTP. Sur GeOsm, les données sont rafraîchies chaque nuit : une durée de cache de quelques heures suffit, et la plupart des tuiles ne sont calculées qu'une fois par jour. Les zooms les plus consultés peuvent même être générés à l'avance juste après l'import.

tiles/route.ts
app.get("/tiles/:layer/:z/:x/:y.pbf", async (req, reply) => {
  const { layer, z, x, y } = TileParams.parse(req.params); // whitelist of layers, integer z/x/y
  const key = `${layer}/${z}/${x}/${y}`;

  const tile = (await cache.get(key)) ?? (await cache.set(key, await renderTile(layer, z, x, y)));

  return reply
    .header("Content-Type", "application/vnd.mapbox-vector-tile")
    .header("Cache-Control", "public, max-age=3600, stale-while-revalidate=86400")
    .send(tile); // an empty tile is a valid answer: send it, and cache it too
});

Ce qu'on y gagne

Une carte fluide même en 3G, parce qu'une tuile pèse quelques dizaines de kilooctets. Un style modifiable sans retoucher aux données, en clair et en sombre. Des clics qui renvoient les vrais attributs des objets. Et une seule source de vérité : la base PostGIS, la même que celle qui sert aux analyses et aux extractions. Pour une plateforme pensée pour l'Afrique, où la connexion mobile est la norme, ce n'est pas un détail d'optimisation : c'est la condition pour que la carte soit utilisable.

À lire ensuite