OGC WMS/WMTS/TMS · live PostGIS
Every other demo here reads a file. This one reads a database: a 63 GB PostGIS table holding 154.8 million OpenStreetMap features across Germany, France, the Netherlands, Belgium and Luxembourg, queried live, per tile. It also runs on the grid the EU itself publishes for pan-European data, EuropeanETRS89_LAEAQuad (EPSG:3035, INSPIRE's own equal-area grid), not Web Mercator. The zoom levels most people actually browse are precomputed archives, read in about a millisecond; zoom in past them and you're watching a live spatial query answer instead.

The approach
The swiss demo proved TerraServe can serve any tile grid. This one does it at EU scale, on the grid INSPIRE actually specifies for pan-European datasets: EPSG:3035, a Lambert azimuthal equal-area projection with its own origin and cell sizes, published as one OGC TileMatrixSet document the viewer reads directly, so raster and vector tiles can't drift out of registration with each other.
Every other example on this site opens a file. This one queries PostGIS: for a given tile, only the rows inside that tile's bbox are ever fetched, so a request for one Frankfurt block never touches the other 154.7 million features. The same windowed-read discipline as the vida demo, just against a live relational database instead of a flat file.
The zoom range most visitors actually use, continent down to city, is pre-baked to tile archives for all five layers, both as vector tiles and as ready-made raster images. A z9 tile from the archive has measured at about 1.1 ms. Zoom in past z10 and PostGIS answers directly, live, still scoped to just the tile in view.
The honest part
The buildings archive was baked with the same size gate every other layer uses: skip shapes smaller than a set number of pixels, so overview zooms aren't crowded with dust. At most zooms, on most datasets, that's invisible. At this grid's zoom 0, a pixel covers about 17.5 km on a side, so a gate of even a single pixel demands a building bigger than 309 km² to survive. No building on Earth clears that bar. The bake didn't thin the buildings layer at the shallowest zooms, it wrote zero tiles for it, silently, and a visitor who zoomed all the way out got a live query against 107.9 million rows instead, which is exactly the request that used to time out.
Fixed by re-baking buildings ungated for its full z0-10 range, the same choice its own raster archive had already made for the same reason. The lesson generalizes past this one layer: any threshold tuned for a comfortable middle zoom can silently produce nothing, not just less, at the far end of the range. Check the shallowest zoom explicitly, every time.

Industrial, commercial, retail, warehouse, school and hospital each get their own colour from a single MapLibre style file. That file is global to the process, not per layer, so water/roads/landuse/places on this demo fall through to its default colour rather than being individually themed, a real, disclosed limitation of a one-style-file-per-process design.
The X-ray viewer's raster underlay reads through /wmts, which serves the same z0-10 archive as the vector tiles, so switching it on costs nothing extra inside the archived range. Past z10 it renders live from PostGIS, same as the vector layer above it, so the two never fall out of sync.
How it's served
One process, five layers, one YAML config. Most of the flags below exist because of the bug above.
terraserve serve # 154.8M OSM features, five layers, one config --config /data/eu5/eu5.yaml # buildings, roads, water, landuse, places --mvt-style /data/eu5/eu5.mvt-style.json --mvt-min-feature-px 1.0 --raster-min-feature-px 0.05 # ~40x apart, on purpose --mvt-cache 512 --wms-cache 512 --max-inflight 8 --public-url https://terraserve.io/demo/eu5
| --config eu5.yaml | Five layers in one YAML file: buildings, roads, water, landuse, places. Each has its own PostGIS table, its own grid list, and its own precomputed archive paths. One process serves all five. |
| grids: [EuropeanETRS89_LAEAQuad.json] | The OGC-registered EU grid, EPSG:3035, written out as one TileMatrixSet JSON file, the same mechanism the swiss demo uses for its national grid, here at continental scale instead. |
| --mvt-style eu5.mvt-style.json | A match() expression keyed on the building tag: industrial, commercial, retail, warehouse, school and hospital each get a colour. --mvt-style is global per process, not per layer, so it also governs water/roads/landuse/places on this demo, and they fall through to its default colour. |
| --mvt-min-feature-px 1.0 | The cartographic gate: skip shapes under about 295 m² at this grid's zoom 10. Tuned down from a 2.0 default that was erasing roughly half of every building footprint at LAEA's resolution. |
| --raster-min-feature-px 0.05 | The safety gate for the raster path, deliberately about 40× smaller than the MVT one. Still bounds a worst-case request to 0.07 GiB instead of 52.6 GiB, without visibly thinning the map. |
| TERRASERVE_PG_STATEMENT_TIMEOUT_MS=90000 | Raised 3× from Postgres's own 30 s default, after a live request over nearly a whole country outlasted it. A safety margin for an occasional wide request, not a promise every bbox now succeeds. |
| TERRASERVE_PG_MAX_QUERY_FEATURES=150000000 | The correctness knob a table this large needs: the 500,000 default would silently truncate a 107.9-million-row table with no ORDER BY, so two identical requests could return different tiles. |
Measured on the live server: a z9 tile from the buildings archive returns in about 1.1 ms. Archive coverage across all five layers is now gap-free from z0 to z10, the buildings archive originally shipped without z0/z1 at all, for the reason above, and that was found and fixed the same day it went live.
Source & attribution. OpenStreetMap data for Germany, France, the Netherlands, Belgium and Luxembourg, extracts via Geofabrik, © OpenStreetMap contributors, ODbL. Tile grid: EuropeanETRS89_LAEAQuad (EPSG:3035), the equal-area Lambert azimuthal grid the EU publishes for INSPIRE data, written as an OGC TileMatrixSet.