Mapbox Data Strategy: Choosing Between Vector Tiles and GeoJSON
Learn when to use Mapbox Vector Tiles (MVT) versus GeoJSON based on data volume, update frequency, and client-side memory constraints.
02 Sept 2025, 04:33 UTC

The primary performance bottleneck in Mapbox GL JS is rarely the rendering engine, but rather how data is delivered to the browser. Using GeoJSON for massive datasets often leads to UI thread blocking as the browser parses large JSON strings, while using Mapbox Vector Tiles (MVT) for small, highly dynamic data introduces unnecessary architectural overhead.
The decision depends on data volume and update frequency. Use GeoJSON for datasets under 5MB where you need instant individual feature updates; use MVT for datasets exceeding 10,000 features or complex geometries where smooth zooming and panning are critical.
Comparative Decision Matrix
| Constraint | GeoJSON | Mapbox Vector Tiles (MVT) |
|---|---|---|
| Ideal Dataset Size | < 5MB / Low feature count | Large / High vertex density |
| Update Latency | Near real-time (Individual features) | Higher (Requires tile refresh/rebuild) |
| Client Memory | High (Full geometry stored in RAM) | Low (Only visible tiles loaded) |
| Setup Complexity | Simple (Standard REST API) | Complex (Requires tiling pipeline) |
| Styling | Client-side JS logic | GL-expressions (Data-driven) |
Trade-offs for GeoJSON
GeoJSON is a text-based format. When passed to a Mapbox source, the browser must parse the entire string into JavaScript objects. This process is "blocking," meaning the map will stutter or become unresponsive if the payload is too large.
GeoJSON is the superior choice for dynamic dashboards. For example, if you are tracking 50 delivery vehicles that move every few seconds, you can update the source using setData() without the overhead of re-calculating a tile grid or waiting for a server to generate new binary files.
Trade-offs for Vector Tiles (MVT)
MVT slices data into square "tiles" based on zoom levels. The browser only downloads data for the visible viewport. MVT also employs decimation—simplifying complex geometries at lower zoom levels to reduce the number of vertices the GPU must process.
MVT is mandatory for static or semi-static layers like city boundaries or property parcels. Because tiles are binary (Protobuf), they transfer faster over the network than equivalent JSON and reduce the memory footprint on the client device.
Implementation: Configuring an MVT Source
To use MVT, you need a backend that serves .pbf or .mvt files (generated via tools like Tippecanoe or PostGIS). Run the following configuration in your Mapbox GL JS initialization script:
// Add the vector tile source
// Required: A valid MVT endpoint and appropriate CORS permissions
map.addSource('large-dataset-source', {
'type': 'vector',
'tiles': ['https://api.yourdomain.com/tiles/{z}/{x}/{y}.pbf'],
'maxzoom': 14
});
// Add the layer referencing the specific source-layer
map.addLayer({
'id': 'parcels-layer',
'type': 'fill',
'source': 'large-dataset-source',
'source-layer': 'properties', // Must match the layer name inside the MVT
'paint': {
'fill-color': '#61bb66',
'fill-opacity': 0.5
}
});
Risk and Verification
The primary risk with MVT is "tile gaps" or missing data if the maxzoom is set incorrectly or if the tiling pipeline does not properly handle feature clipping at tile boundaries.
To verify the performance gain, use Chrome DevTools:
- Memory Tab: Take a heap snapshot before and after loading your data. If a GeoJSON layer causes a spike of 100MB+, migrate to MVT.
- Network Tab: Pan rapidly across the map. In an MVT implementation, you should see small, frequent requests for
.pbffiles rather than one massive initial JSON download.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.