Skip to content
← Back to blog
Web DevelopmentOctober 10, 2026

Web Maps That Stay Fast: GeoJSON vs Vector Tiles with MapLibre

Why a web map with a big GeoJSON file slows down, how vector tiles fix it, and a minimal MapLibre page you can run today.

web-developmentWeb GIS

A common first web map loads a GeoJSON file and draws it. With 200 features it feels instant. With 200,000 the page freezes, the phone gets hot and someone asks why the map is slow.

The fix is rarely a faster server. It is a different way of delivering the data.

What is a web map made of?

A web map has two parts that people often mix up.

  • The map library runs in the browser and draws the map. Examples are MapLibre GL JS and Leaflet.
  • The data is what the library draws. It arrives as images (raster tiles), as vector data in one piece (GeoJSON), or as small vector pieces (vector tiles).

GeoJSON is a text format for features. By the GeoJSON specification (RFC 7946), coordinates are longitude then latitude in WGS 84, which is EPSG:4326. Note the order: longitude comes first, which is the opposite of how latitude and longitude are usually said aloud.

Vector tiles cut the map into a grid of squares at each zoom level. Each tile holds only the features that fall in it, in a compact binary format, simplified for that zoom. The common format is Mapbox Vector Tile (MVT).

Why it matters

With GeoJSON, the browser downloads everything and keeps every vertex in memory, whatever the zoom level. At a country-wide view, it draws detail nobody can see.

With vector tiles, the browser requests only the tiles in view, and at low zoom the geometry is simplified. The work moves to the point where it is cheapest: once, when you build the tiles.

How it works

Tile maps use the Web Mercator projection (EPSG:3857). At zoom level 0 the whole world is one tile. Each zoom level splits every tile into four, so zoom z has 2^z × 2^z tiles. A tile address is z/x/y, and the browser works out which addresses cover the screen and requests those.

This is why tile data has to be generated ahead of time, or by a service that does it on request. Tools like Tippecanoe, or PostGIS functions that produce tiles, do that job.

Web Mercator is fine for display, and poor for measurement, especially for area at high latitudes. Do your area and distance analysis in a suitable projected CRS before or outside the web map.

Practical GIS example

A minimal MapLibre page that shows a GeoJSON layer. This is the right starting point for small data, and it is the version you will later replace with a tile source.

<!-- A minimal MapLibre GL JS map with one GeoJSON layer. Save as index.html. -->
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <link rel="stylesheet" href="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css" />
  <script src="https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js"></script>
  <style>
    body { margin: 0; }
    #map { height: 100vh; }
  </style>
</head>
<body>
  <div id="map"></div>
  <script>
    // Step 1: Create the map, centred on Pune (longitude first)
    const map = new maplibregl.Map({
      container: "map",
      style: "https://demotiles.maplibre.org/style.json",
      center: [73.8567, 18.5204],
      zoom: 10
    });

    map.on("load", () => {
      // Step 2: Add the data as a source
      map.addSource("places", {
        type: "geojson",
        data: {
          type: "FeatureCollection",
          features: [
            { type: "Feature",
              properties: { name: "Shaniwar Wada" },
              geometry: { type: "Point", coordinates: [73.8553, 18.5195] } }
          ]
        }
      });

      // Step 3: Add a layer that draws the source
      map.addLayer({
        id: "places-layer",
        type: "circle",
        source: "places",
        paint: { "circle-radius": 8, "circle-color": "#d1495b" }
      });
    });
  </script>
</body>
</html>

Open the file in a browser and the point appears. To switch to vector tiles later, only Step 2 changes: the source becomes type: "vector" with a tiles URL, and the layer gains a "source-layer" name that matches the layer inside the tiles.

Workflow for a larger layer

  1. Reproject the data to EPSG:4326 if it is not already (GeoJSON expects it; tile tools usually do this step for you, so check their docs).
  2. Build tiles from the layer, for example with Tippecanoe, into one .mbtiles or .pmtiles file.
  3. Serve the tiles from a tile server, or from static storage if you use PMTiles.
  4. Point a MapLibre vector source at the tiles and style the layers.
  5. Open the network tab, pan and zoom, and look at what actually gets transferred.

Best practices

  • Begin with the user's task. Who uses the map, on what device, to do what?
  • Choose the data delivery by size. Small and static: GeoJSON. Large or zoom-dependent: vector tiles. Imagery: raster tiles or COG.
  • Cache. Tiles are static files, so a CDN works well.
  • Plan permissions early. Decide which layers and attributes each role can see before building the API.
  • Build in slices. Map first, then filters, then analysis, then export.
  • Measure. Log load times and failed requests so you find problems before users report them.

Common mistakes

  • Loading a huge GeoJSON and blaming the browser.
  • Swapping latitude and longitude. GeoJSON and MapLibre use longitude first. A point that lands in the wrong ocean is usually this.
  • Doing analysis in Web Mercator. It distorts area. Use it for display only.
  • Putting every attribute in the tiles. Extra properties make every tile larger. Keep only what the map needs and fetch the rest on click.
  • No attribution. Basemaps and data have licence terms that require credit.

Key takeaways

  • The browser draws, the data format decides how fast.
  • GeoJSON for small data, vector tiles for large data.
  • Coordinates in GeoJSON are longitude, latitude in EPSG:4326; tiles are displayed in EPSG:3857.
  • Display in Web Mercator, analyse in an appropriate projected CRS.
  • Use the browser's network tab to check, not guess.
T&S
Time & Spatial
Engineers who've shipped real systems
Share