MediumVector Tiles (MVTs) in Modern Map Applications | by M. Ali Khan | Venture
Sitemap
Venture

Thought leadership and essential resources for entrepreneurs, indie hackers, and startups.

Vector Tiles (MVTs) in Modern Map Applications

12 min readAug 9, 2026

--

Modern map applications can display thousands or even millions of geographic features while still providing a smooth experience.

A user can pan across a city, zoom into a neighborhood, and see roads, buildings, boundaries, fields, and points appear almost instantly.

But geographic data can become extremely large.

A database might contain millions of geometries, and sending all of that data to a browser would be inefficient. The browser would have to download, parse, store, and render data that the user may never even see.

This is where Vector Tiles, commonly referred to as MVTs (Mapbox Vector Tiles), become useful.

Although the specification is commonly known by the Mapbox Vector Tile name, the technology is not limited to Mapbox-based applications. MVTs are widely used as a vector tile format with different map renderers, tile servers, databases, and mapping platforms.

The core idea is simple:

Instead of sending the entire geographic dataset to the browser, send only the geographic data required for the part of the map the user is currently viewing.

The Problem With Large Geographic Datasets

Let’s start with a format that most web developers are familiar with: GeoJSON.

GeoJSON is a convenient way of representing geographic data.

A simple feature might look like:

{ 
"type": "Feature",
"properties": {
"name": "Islamabad"
},
"geometry": {
"type": "Point",
"coordinates": [73.0479, 33.6844]
}
}

For small datasets, GeoJSON works extremely well.

If an application needs to display a few hundred locations, returning a GeoJSON FeatureCollection is usually straightforward.

The situation changes when the dataset becomes large.

Imagine a GIS application containing:

  • millions of road segments
  • hundreds of thousands of buildings
  • large administrative boundaries
  • millions of points
  • agricultural field polygons
  • detailed land-use data

Returning all of this as one GeoJSON response would create several problems.

The response could become very large.

The network would have to transfer unnecessary data.

The browser would need to parse a large JSON document.

Memory usage would increase.

Rendering could become expensive.

Most importantly, the user might only be viewing a tiny fraction of the dataset.

If the user is looking at one neighborhood, there is little reason to send geographic data covering an entire country.

The Idea Behind Tiling

The solution is to divide geographic space into smaller pieces called tiles.

Instead of treating the entire map as one dataset, the world is divided into a grid.

A tile is identified using three values:

Z / X / Y

These represent:

  • Z — zoom level
  • X — horizontal tile coordinate
  • Y — vertical tile coordinate

A tile URL might look like:

/tiles/10/689/423.pbf

Here:

Z = 10
X = 689
Y = 423

Together, these coordinates identify a particular geographic area.

When the user moves the map, the mapping library determines which tiles are required and requests them from the server.

The overall process looks something like this:

User moves or zooms the map 
↓
Map determines required tiles
↓
Requests Z/X/Y tiles
↓
Tile server retrieves geographic data
↓
Data is encoded as MVT
↓
Browser receives the tile
↓
Map renderer displays the features

Instead of downloading the entire dataset, the browser receives only the pieces it needs.

What Is an MVT?

MVT stands for Mapbox Vector Tile.

It is a specification for representing vector geographic data inside tiles.

The important word here is vector.

An MVT does not contain a rendered map image.

Instead, it contains geographic features such as:

  • points
  • lines
  • polygons
  • feature attributes
  • layers

The data is encoded using a compact binary representation based on Protocol Buffers.

MVT files are commonly served using the .pbf extension.

For example:

/tiles/12/2201/1432.pbf

The browser receives this binary data and the map rendering library interprets the geographic features contained inside it.

Vector Tiles vs Raster Tiles

To understand MVTs properly, it helps to compare them with raster tiles.

A traditional raster tile is essentially an image.

For example:

256 × 256 PNG

The server has already rendered the map.

The browser receives pixels.

If a road is blue, the image simply contains blue pixels representing that road.

The client does not know that those pixels represent a road.

Vector tiles are fundamentally different.

Instead of receiving the final image, the browser receives vector information.

For example:

Road
Type: highway
Name: Main Road
Geometry: LineString

The rendering engine can then decide how that road should appear.

This allows applications to dynamically style geographic data.

The same vector data could potentially be displayed using different colors, widths, visibility rules, or styles without regenerating the underlying geographic data.

MVT Is Not Simply GeoJSON Split Into Tiles

It is easy to think of MVTs as:

“GeoJSON divided into smaller files.”

That is not quite accurate.

GeoJSON is a human-readable, text-based format based on JSON.

MVTs use a compact binary representation designed specifically for tiled vector data.

This difference matters.

Consider a large geographic dataset.

With GeoJSON, you might have:

Large JSON response 
↓
Download
↓
Parse entire document
↓
Process features
↓
Render

With vector tiles:

Map viewport 
↓
Required tiles
↓
Binary MVT data
↓
Decode
↓
Render relevant features

The advantage isn’t simply that the data is binary.

The real advantage comes from combining binary encoding with spatial tiling and viewport-based loading.

Understanding Z, X, and Y

The Z/X/Y addressing system is fundamental to web mapping.

Zoom

The zoom level determines the level of detail.

At low zoom levels, each tile covers a large geographic area.

At higher zoom levels, the geographic area represented by each tile becomes smaller.

Conceptually:

Low zoom

+------------------------+
| |
| WORLD |
| |
+------------------------+

At a higher zoom level:

At a higher zoom level:

+----------+----------+
| | |
| Tile | Tile |
| | |
+----------+----------+
| | |
| Tile | Tile |
| | |
+----------+----------+

At even higher zoom levels, the world is divided into many more tiles.

This allows map applications to request geographic data at an appropriate level of detail.

X and Y Identify the Location

Once the zoom level is known, X and Y identify a particular tile within that zoom level.

For example:

10/689/423

means:

Zoom = 10
X = 689
Y = 423

A tile service can expose these using a standard URL pattern:

https://example.com/tiles/{z}/{x}/{y}.pbf

A map renderer replaces the placeholders with the actual tile coordinates.

The server can then use those coordinates to determine the geographic extent that needs to be queried.

Where Does the Geographic Data Come From?

MVTs are only a data-delivery format.

Something still has to generate them.

A common architecture for GIS applications looks like this:\

Map Application 
|
|
v
Map Renderer
|
|
Z/X/Y request
|
v
Tile Server
|
|
Spatial Query
|
v
PostGIS
|
v
Geographic Dataset

The database stores the actual geographic information.

The tile server receives a tile request.

It queries the relevant geographic features.

Those features are transformed into tile geometry.

The result is encoded as MVT.

The tile is then returned to the client.

MVTs and PostGIS

One of the most useful combinations for web GIS applications is:

PostgreSQL
+
PostGIS
+
MVT
+
Vector Map Renderer

PostGIS provides spatial functionality inside PostgreSQL.

It allows applications to store geometries such as:

POINT
LINESTRING
POLYGON
MULTIPOINT
MULTILINESTRING
MULTIPOLYGON

It also provides spatial operations such as:

ST_Intersects()
ST_Contains()
ST_Within()
ST_DWithin()

Most importantly for vector tiles, PostGIS provides functions for generating MVTs.

Three particularly important functions are:

ST_TileEnvelope()
ST_AsMVTGeom()
ST_AsMVT()

A simplified query could look like:

WITH tile AS (
SELECT ST_TileEnvelope(10, 689, 423) AS bounds
)
SELECT ST_AsMVT(mvtgeom, 'roads')
FROM (
SELECT
id,
name,
ST_AsMVTGeom(
geometry,
tile.bounds
) AS geom
FROM roads, tile
WHERE geometry && tile.bounds
) AS mvtgeom;

This is a simplified example, but it demonstrates the general architecture.

The application provides:

Z = 10
X = 689
Y = 423

ST_TileEnvelope() determines the geographic extent of that tile.

The spatial query finds relevant features.

ST_AsMVTGeom() prepares the geometries for the tile.

Finally, ST_AsMVT() encodes the result as an MVT.

The resulting binary tile can then be returned to the map client.

What Does ST_TileEnvelope Do?

ST_TileEnvelope() is responsible for determining the geographic bounds of a particular tile.

For example:

ST_TileEnvelope(10, 689, 423)

returns the spatial extent associated with that tile.

This is important because the database needs to know:

“Which part of the world does this tile represent?”

Once the database knows the tile’s geographic extent, it can perform a spatial query against the dataset.

Instead of asking:

Give me every road.

the application effectively asks:

Give me the roads relevant to this geographic tile.

That is a much more scalable operation.

What Does ST_AsMVTGeom Do?

A geometry stored in PostGIS is not automatically ready to be placed inside an MVT.

Get M. Ali Khan’s stories in your inbox

Join Medium for free to get updates from this writer.

MVTs use a tile-specific coordinate system.

ST_AsMVTGeom() prepares the geometry for that tile.

Conceptually:

PostGIS Geometry
↓
Tile Bounds
↓
Geometry Transformation
↓
Clipping / Preparation
↓
MVT Geometry

This process makes the geometry suitable for vector tile encoding.

Why Geometry Clipping Matters

Consider a road that crosses several tiles.

The road might look like this:

+---------------------+
| / |
| / |
| / |
| / |
+-----/---------------+
/
/

The entire road does not necessarily need to be included in every tile.

The geometry can be clipped around tile boundaries.

Each tile can therefore contain the portion of the geometry relevant to it.

This reduces unnecessary data and makes vector tiles more efficient.

Layers Inside Vector Tiles

An MVT can contain multiple layers.

For example:

Tile 
│
├── roads
├── buildings
├── water
├── boundaries
└── places

This allows different categories of geographic information to be represented independently.

A map renderer can then apply different styling rules to each layer.

For example:

roads → road styling 
buildings → building
styling water → water
styling boundaries → boundary
styling places → labels

This is another major advantage of vector data.

The geographic data and the visual presentation can be separated.

Zoom-Dependent Data

Another important concept in vector tiles is level of detail.

Not every feature needs to be displayed at every zoom level.

Consider a road network.

At a national level, displaying every tiny residential street would make little sense.

At a neighborhood level, those streets become important.

An application can therefore use different levels of geographic detail:

Zoom 4 Major highways 
Zoom 8 Highways + major roads
Zoom 12 Road network
Zoom 16 Detailed streets

This can be achieved through different datasets, filtering rules, geometry generalization, or styling rules depending on the application.

The objective is always the same:

Don’t process or display more geographic detail than the current map scale requires.

MVTs and Map Rendering Libraries

MVTs are not tied to one particular frontend framework or mapping application.

A web application can use a vector-map renderer capable of consuming vector tiles.

For example, applications can integrate vector tiles with libraries such as:

  • MapLibre GL JS
  • OpenLayers
  • other compatible mapping engines and GIS clients

The general flow remains:

MVT 
↓
Map Renderer
↓
GPU / Rendering Engine
↓
Screen

The frontend framework could be React, Next.js, Angular, Vue, or something else entirely.

The framework manages the application.

The map renderer manages the geographic visualization.

The tile server manages geographic data delivery.

These concerns can remain separate.

GeoJSON vs MVT

So when should you use GeoJSON and when should you use MVT?

There is no universal rule.

GeoJSON is often a good choice when:

  • the dataset is relatively small
  • features need to be edited
  • the complete dataset is required
  • data exchange is more important than rendering performance
  • human readability is useful

MVTs become attractive when:

  • the dataset is large
  • the map is interactive
  • users move around different geographic areas
  • the application needs smooth zooming and panning
  • only a subset of the dataset is needed at a time
  • the same geographic dataset is being rendered repeatedly

In many applications, both formats can coexist.

For example:

MVT 
↓
Large map visualization GeoJSON
↓
Selected feature
↓
Editing / analysis

MVTs don’t replace GeoJSON.

They solve a different problem.

Spatial Indexing Still Matters

There is an important misconception worth addressing.

Using MVTs does not automatically make a spatial application fast.

The tile generation process still depends on the underlying spatial queries.

Imagine a database containing millions of geometries.

If every tile request causes PostgreSQL to scan the entire table, the tile service can still become slow.

This is why spatial indexes are important.

A typical PostGIS geometry column might use a GiST index:

CREATE INDEX roads_geometry_idx
ON roads
USING GIST (geometry);

The exact indexing strategy depends on the dataset and workload.

But the principle is simple:

Efficient vector tiles require efficient spatial queries.

MVTs improve the data-delivery architecture, but they don’t eliminate database optimization.

Caching Vector Tiles

Another major advantage of tiled architectures is caching.

Tiles have predictable addresses:

/{z}/{x}/{y}.pbf

That makes them well suited to HTTP caching and CDNs.

A production architecture might look like:

Map Client 
↓
CDN / Cache
↓
Tile Server
↓
PostGIS

Suppose 1,000 users request the same tile.

Without caching, the tile server might repeatedly query the database.

With caching, the first request can generate the tile and subsequent requests can retrieve the cached version.

Conceptually:

First request 
↓
Cache MISS
↓
Tile Server
↓
PostGIS
↓
MVT
↓
Cache Later requests
↓
Cache HIT
↓
MVT

This can significantly reduce database load.

MVTs and Large-Scale GIS

The architecture becomes particularly useful for applications dealing with large geographic datasets.

Agriculture

Agricultural platforms may contain millions of field boundaries.

Users might zoom from a country-level view down to individual fields.

Vector tiles allow the application to progressively load geographic information as the user navigates.

Logistics

A logistics platform may contain:

roads
warehouses
delivery locations
routes
administrative boundaries

Instead of sending everything to the browser, the application can deliver the relevant tiles.

Real Estate

A property platform might contain thousands or millions of property boundaries.

Vector tiles can provide efficient visualization while allowing properties to be styled based on attributes.

Environmental Applications

GIS applications can contain:

flood zones
land-use polygons
forest boundaries
risk areas
water bodies

Large spatial datasets become much easier to visualize when delivered tile by tile.

Navigation

Navigation applications are another obvious example.

Road networks are enormous.

A client does not need the entire global road network every time a map is opened.

It needs the geographic information relevant to the current location and zoom level.

The Architecture in One Picture

Putting everything together, a modern vector-tile architecture might look like this:

┌─────────────────────┐
│ Web App │
│ React / Angular etc.│
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Map Renderer │
│ Vector-capable │
└──────────┬──────────┘
│
Z/X/Y
│
▼
┌─────────────────────┐
│ CDN / Cache │
└──────────┬──────────┘
│
Cache Miss
│
▼
┌─────────────────────┐
│ Tile Server │
└──────────┬──────────┘
│
Spatial Query
│
▼
┌─────────────────────┐
│ PostgreSQL + PostGIS│
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Geographic Dataset │
└─────────────────────┘

Each component has a different responsibility.

The database stores the data.

PostGIS performs spatial operations.

The tile server generates or serves tiles.

The cache reduces repeated work.

The map renderer displays the vector data.

The frontend provides the surrounding application.

This separation is what makes the architecture scalable.

The Most Important Idea

It is easy to describe MVTs as:

“A binary format for vector tiles.”

That is technically correct, but it doesn’t capture why they are important.

The bigger idea is spatially aware data delivery.

A traditional API might ask:

GET /roads

and return a large collection of roads.

A vector tile API asks something closer to:

GET /tiles/{z}/{x}/{y}

The request itself tells the server which part of geographic space the client is interested in.

That changes the architecture completely.

The application is no longer transferring a dataset.

It is streaming the map’s geographic information based on the user’s interaction with the map.

MVTs Are a Delivery Architecture, Not Just a File Format

The real power of MVTs comes from combining several ideas:

Spatial partitioning 
+
Viewport-based loading
+
Zoom-dependent detail
+
Binary encoding
+
Geometry clipping
+
Spatial indexing
+
Caching
+
Client-side rendering

None of these ideas alone solves every performance problem.

Together, however, they create an efficient way to deliver large geographic datasets to interactive applications.

This is why vector tiles have become such an important part of modern web GIS.

Final Thoughts

Large-scale map applications have a fundamental problem:

Geographic data is often much larger than what the user actually needs to see.

MVTs provide a practical solution.

Instead of sending an entire dataset to the browser, geographic data is divided into tiles.

The client requests the tiles required for its current viewport.

The server retrieves the relevant geographic features.

PostGIS can perform the spatial queries and generate the vector tile.

A tile server can deliver the result.

A CDN can cache frequently requested tiles.

And a vector-capable map renderer can turn those features into an interactive map.

The result is a system where the user can interact with very large geographic datasets without having to download those datasets in their entirety.

That is the real value of MVTs.

They aren’t simply a replacement for GeoJSON.

They represent a different way of thinking about how geographic data should be delivered:

Don’t send the entire map. Send the pieces of geographic information the user needs, when they need them.

Before you go

  • Please take a moment to like the post and follow the writer!
  • Did you know that over 400,000 developers share what they’re building, learning, and discovering across our platforms every month? Learn how you can contribute here.

--

--