When to Use Vector Tiles Over Raster for Web Maps
Use vector tiles when your stack requires client-side styling, feature-level interactivity, or decoupled style deployment — and your source data is structured geometry rather than continuous-tone imagery.
When to Use Vector Tiles: Concrete Conditions
The following conditions are sufficient individually to justify vector tiles. Meeting two or more makes raster impractical for new infrastructure.
| Condition | Why vector wins | Raster alternative cost |
|---|---|---|
| Client-side feature interactivity | Geometry preserved in browser; queryRenderedFeatures() works at any zoom |
WMS GetFeatureInfo round-trip per click; 80–400 ms latency |
| Multiple themes / dark mode | Style JSON swap; zero tile regeneration | Separate raster tileset per theme; 2–10× storage |
| Style updates faster than data changes | Deploy new style.json; existing .pbf cache stays valid |
Full raster tileset rebuild on every symbol or color change |
| CDN-cached geometry for multiple views | One .pbf set powers all style variants |
N raster sets, each independently invalidated |
| Python-driven automated generation pipeline | Idempotent Tippecanoe run; content-addressed .pbf hashes |
Server-side renderer must re-bake every zoom/style combination |
| Multilingual labels | Language switched at runtime from feature attribute | Pre-baked into pixels; separate raster tileset per locale |
Raster tiles remain correct for: aerial/satellite imagery, hillshade terrain composites, pixel-level blending (multi-band rasters), and environments where WebGL is unavailable or GPU/CPU is severely constrained.
Specification Detail
The Mapbox Vector Tile (MVT) specification defines the binary format that .pbf tile files use. Key parameters that determine whether vector tiles are viable for a given dataset:
| Parameter | Value / range | Notes |
|---|---|---|
| Tile coordinate space | 4096 × 4096 units per tile | Sub-pixel precision at most zoom levels |
| Max recommended tile size | 500 KB uncompressed | Larger triggers rendering stalls in MapLibre |
| Geometry types | Point, LineString, Polygon | No raster or coverage data types |
| Attribute value types | Int, float, string, bool | No binary blobs; filter predicates use these types |
| Protobuf compression | Gzip or Brotli at the HTTP layer | Not encoded into the .pbf itself |
| Zoom range supported | z0–z22 | Tippecanoe defaults to z0–z14 unless overridden |
Tiles are stored in either an MBTiles SQLite container for local tooling or a PMTiles archive for CDN range-request delivery. The PMTiles format uses HTTP range requests to serve individual tiles without a tile server process, which eliminates origin infrastructure for static datasets.
Production Command
The following Tippecanoe invocation generates a production .mbtiles tileset from a GeoJSON source, with attributes pruned to the minimum needed for styling and interactivity. It demonstrates the flags that directly control the vector-vs-raster decision axes: tile size, attribute retention, and zoom range.
tippecanoe \
--output=output/roads.mbtiles \
--maximum-zoom=14 \
--minimum-zoom=5 \
--drop-densest-as-needed \
--extend-zooms-if-still-dropping \
--include=name \
--include=highway \
--include=oneway \
--simplification=4 \
--force \
data/roads.geojson
Flag annotations:
--drop-densest-as-needed— drops features at lower zooms to keep tiles under 500 KB, preserving the vector payload budget--extend-zooms-if-still-dropping— adds zoom levels automatically if the dataset is too dense to fit at--maximum-zoom--include=name,highway,oneway— drops every attribute not needed by the style, a direct application of dropping unused attributes to reduce tile size--simplification=4— controls geometry simplification aggressiveness; higher values reduce vertex count at the cost of shape fidelity
For a GeoParquet source (common in large-scale Python ETL), pipe through GDAL or the converting-large-geoparquet-files workflow before feeding Tippecanoe:
ogr2ogr \
-f GeoJSON /vsistdout/ \
data/parcels.geoparquet \
-t_srs EPSG:4326 | \
tippecanoe \
--output=output/parcels.mbtiles \
--maximum-zoom=16 \
--drop-smallest-as-needed \
--include=parcel_id \
--include=land_use \
--force \
/dev/stdin
Input must be EPSG:4326 (geographic WGS 84). Tippecanoe reprojects internally to the tile coordinate space (EPSG:3857 web Mercator) during encoding.
Interaction Effects
Vector tile viability depends on three flags working together. Changing one without considering the others causes tile size or rendering problems.
--maximum-zoom and tile payload size
Higher --maximum-zoom values increase vertex density per tile because generalization is finer. At z16+ for dense urban parcel data, uncompressed tile sizes routinely exceed 500 KB without attribute pruning. Pair --maximum-zoom=16 with aggressive --include allowlisting and --simplification=8 to stay within budget. See calculating optimal max zoom for urban datasets for the tile-size-vs-zoom trade-off in detail.
--simplification and geometry fidelity
The Visvalingam vs Douglas-Peucker comparison matters here: Tippecanoe uses a variant of Visvalingam-Whyatt by default. At --simplification=4 (the recommended starting point for roads), vertex count drops 30–60% at z10 without visible artifacts at typical viewport zoom levels. Increasing to --simplification=10 reduces tile size a further 15–25% but produces noticeably jagged polygons when users zoom in.
Attribute filtering and queryRenderedFeatures()
MapLibre’s queryRenderedFeatures() only returns attributes present in the tile. If an attribute is dropped by --include allowlisting, it is invisible to click handlers and runtime filter expressions, even if it exists in the source. Define your style’s filter and popup attribute list before finalizing the --include set.
Performance Impact
Typical measurements across a 500 MB GeoJSON roads dataset (OpenStreetMap extract, Western Europe):
| Metric | Vector tiles (z0–z14) | Raster tiles (z0–z14, 256 px PNG) |
|---|---|---|
| Total tileset size | 1.2 GB (MBTiles) | 18–40 GB (depending on symbology) |
| Generation time | 8 min (Tippecanoe, 8 cores) | 2–6 hours (server-side renderer) |
| Per-tile transfer (z12, urban) | 35–80 KB .pbf + gzip |
60–130 KB PNG |
| Style update cost | 0 (new style.json deploy) |
Full raster rebuild |
| Client render time (z12, desktop) | 8–20 ms (WebGL, MapLibre) | 2–5 ms (image decode + draw) |
| Client render time (z12, low-end mobile) | 40–120 ms | 5–15 ms |
The client render overhead on low-end mobile is the primary reason to stay raster when targeting broad consumer audiences without device profiling. A 120 ms frame budget hit at z12 causes visible jank during pan gestures.
CDN cache efficiency is strongly in vector’s favor: one .pbf tileset serves every style variant. Raster caches multiply linearly with the number of distinct themes or locales.
Common Mistakes
Sending un-pruned attributes in vector tiles
Symptom: tiles consistently exceed 500 KB at z14+; MapLibre logs Tile size limit exceeded warnings in the browser console.
# Diagnose: inspect attribute payload fraction
tippecanoe-decode output/parcels.mbtiles 14 8192 5461 | \
python3 -c "
import sys, json
tile = json.load(sys.stdin)
for layer in tile.get('features', []):
print(layer.get('properties', {}).keys())
" | sort | uniq -c | sort -rn | head -20
Fix: add --include flags to Tippecanoe to allowlist only the attributes your style and click handlers need.
Passing EPSG:3857 input to Tippecanoe
Symptom: tiles render with severe coordinate offset or land in the ocean; no Tippecanoe error is raised.
# Check CRS before ingesting
ogrinfo -al -so data/roads.geojson | grep -i "srs\|crs\|projection"
# Reproject if needed
ogr2ogr -f GeoJSON -t_srs EPSG:4326 data/roads_wgs84.geojson data/roads.geojson
Tippecanoe requires EPSG:4326 (longitude/latitude) input. It handles the tile projection internally.
Choosing vector tiles for a dataset that is effectively imagery
Attempting to vectorize dense 1m-resolution contour lines, hillshade polygons, or land-cover raster classes produces millions of tiny polygons that inflate tile sizes beyond any budget. The symptom is a Tippecanoe run that produces 10–100× the expected tile count with tiles consistently at the 500 KB limit even after maximum simplification.
# Check feature density before committing to vector
ogrinfo -al -so data/contours.geojson | grep "Feature Count"
# If > 5M features for a country-scale dataset, raster is likely correct
Up: Vector vs Raster Tile Tradeoffs
Related
- Vector vs Raster Tile Tradeoffs — the full evaluation workflow covering bandwidth, caching, and reproducible benchmarks for both formats.
- Dropping Unused Attributes to Reduce Tile Size — the
--includeand--excludeflag mechanics that keep vector tile payloads within the 500 KB budget. - Calculating Optimal Max Zoom for Urban Datasets — quantifies the tile size cost of each additional zoom level for dense feature sets.