Buildings · vector
The outline of nearly every building in Spain and Portugal, from the VIDA Open Buildings dataset (built from Google, Microsoft and OpenStreetMap). The file is 3.8 gigabytes, the kind of dataset that crashes a server that tries to load it all. TerraServe just doesn't.

The approach
Most servers open a file by loading all of it into memory. That's impossible here. TerraServe instead keeps a tiny index of where each building sits, and when you look at a neighbourhood it jumps straight to just those buildings and reads only them. Opening the whole 3.8 GB file costs 4 megabytes of memory. A zoomed-in tile draws in 0.085 seconds, at full detail.
Zoom all the way out and a single tile suddenly touches millions of buildings. That's slow and heavy for anyone. So the wide, zoomed-out views are baked ahead of time into a compact archive (a zoomed-out tile that took 40 seconds live now serves in 0.42 seconds). Zoom in, where a tile only touches a few thousand buildings, and TerraServe draws it live on the spot.
The re-bake
The first archive was baked in July 2026, before the tile encoder learned to drop shapes that round away to nothing. It held 3.0 million empty features, 96 % of a typical overview tile, and they filled the per-tile budget, so real buildings were dropped to make room for invisible ones. Over Madrid, the old zoom 4 tile held 19,570 features and only 99 of them were buildings.
A vector tile stores coordinates on a 4,096-unit grid. At zoom 4 one unit is about 611 m, so a house rounds to a single point and cannot be drawn as a polygon. The new --mvt-fine-extent-zoom 6 doubles that grid for each zoom out below 6, so every overview zoom keeps zoom 6's 153 m resolution. Zoom 6 and deeper are byte-identical to before.
One tile per zoom, real buildings, today's encoder on the standard grid against the finer one: zoom 3 0 -> 7,732, zoom 4 10 -> 6,432, zoom 5 316 -> 5,733. Across the whole archive: 0 empty features (was 3.0 million), 33 tiles at the feature cap, all at zoom 10 (was 537), and 277 MB instead of 359 MB.
The opening view, zoomed in and out, three runs in headless Chromium on a real GPU: peak memory 1,652 -> 1,042 MiB, JavaScript heap 1,224 -> 617 MiB, no change to the page. The browser was paying for features nobody could see. The old archive stays on the server for a rollback.
The red and blue blocks are the data. Coloured by source, the map shows straight-edged patches where only OpenStreetMap buildings exist next to areas dense with Microsoft ones. Counting the raw file with GDAL over central Spain, 595 of 1,414 populated 0.1° cells hold no Microsoft buildings at all, in rectangles: that is how the source dataset was assembled, not a tiling seam.
How it's served
The real command behind the live demo. Notice how much shorter it is than cos2023: windowed reading means none of the memory-fitting flags are needed.
terraserve serve # 14.9M Iberia buildings, vector tiles --vector /data/IBERIA.fgb --vec-style /data/vida.sld --name vida --mvt-style /data/vida.mvt-style.json --pmtiles /data/IBERIA.v3-zstd.pmtiles # the baked zoomed-out views (z0 to 10), zstd --tms-grid WebMercatorQuad --tms-tile-px 256 --raster-pmtiles /data/vida.raster.z10.pmtiles # the raster underlay --mvt-cache 512 --wms-cache 512 --max-inflight 8 --tile-max-age 3600 --tile-encoding br --mvt-fine-extent-zoom 6 # the same grid the archive was baked on --public-url https://terraserve.io/demo/vida/wms
| --vector | The data file: a FlatGeoBuf of 14.9 million building outlines. This format carries a built-in index, which is what makes windowed reading possible. |
| --vec-style | How to colour the buildings: an SLD style (here, coloured by which source each building came from). |
| --mvt-style | The matching style for the vector-tile view a browser draws itself. |
| --pmtiles | Trick 2. The pre-baked archive of the zoomed-out views (zoom 0 to 10), served straight off disk. It's read-only here, so no write-back flag is needed. Re-baked in September 2026 with build-pmtiles --mvt-fine-extent-zoom 6 (below), then converted to zstd: 277 MB to 239 MB, every tile checked identical. |
| --tms-grid WebMercatorQuad --tms-tile-px 256 | Publish the tile grid for the WMTS and TMS endpoints, so the viewer can draw a raster underlay. 256 px keeps the grid id the vector archive was baked under. |
| --raster-pmtiles | The same zoom 0 to 10 pre-baked as pictures, for the raster underlay: 8,048 tiles, 18.7 MB. |
| --mvt-cache 512 | Remember recently-drawn zoomed-in tiles (up to 512 MB) so revisiting a neighbourhood is free. |
| --wms-cache 512 | Same idea for the picture (WMS) view. |
| --max-inflight 8 | Draw at most 8 tiles at once, one per core, so a busy moment can't blow up memory. |
| --tile-encoding br | Send live (zoomed-in) tiles as brotli. On a real 246 KB tile from this layer that was 13 % smaller than gzip and faster to produce. A browser that does not accept brotli still gets gzip. |
| --mvt-fine-extent-zoom 6 | Below zoom 6, keep small buildings as real shapes instead of rounding them away (the re-bake above). The archive was baked with 6, so a tile drawn live must use 6 too. |
| --tile-max-age 3600 | Every tile carries an ETag and answers a revisit with a 304; this adds an hour of browser caching, so a revisit costs no request at all. |
| --public-url | The public address to advertise to GIS clients, since it runs behind a web proxy. |
Brotli on the wire, zstd on disk. Since 0.3.3 live tiles go out as brotli (--tile-encoding br, measured smaller than gzip and faster to produce), and the pre-baked archive stores its tiles as zstd: 277 MB to 239 MB (-13.8 %), converted from gzip with terraserve pmtiles-recompress, every tile checked identical. A browser that accepts zstd gets the archive bytes straight off disk; one that does not, such as Safari, gets a brotli copy made once and cached; anything else gets gzip.
Measured: opening the 3.8 GB / 14.9 M-shape file uses 4 MB of memory; a zoomed-in tile renders in 0.085 s at full detail; a zoomed-out tile that took 40 s to draw live now serves from the archive in 0.42 s. This is the demo that would sink a load-everything server. Here, it runs on a small box.
Source. VIDA: Google-Microsoft-Open-Buildings, Iberia subset. Building footprints combined from Google Open Buildings, Microsoft Global ML Buildings, and OpenStreetMap.
In action