PMTiles: Cloud-Native Tile Format for Modern Maps

2026-02-143 min read
PMTilesMBTilesMapLibrecloud-native

Traditional tile servers require a constantly running backend: nginx or a specialized tile server distributes tiles from a directory or database. PMTiles changes this paradigm — one file, static hosting, no servers needed.

What is PMTiles

PMTiles (Protomaps Tiles) is a cloud-native format for storing map tiles in a single file. The key idea is HTTP Range Requests. The client requests only the needed bytes from the file rather than downloading it entirely. This means a PMTiles file can be hosted on any static server: Amazon S3, Cloudflare R2, GitHub Pages, or plain nginx.

The format supports both raster tiles (PNG, JPEG, WebP) and vector tiles (MVT — Mapbox Vector Tiles). Inside the file is a binary tree of indices that locates any tile in O(log n) operations.

Technical specifications:

  • Header size: 127 bytes fixed + variable-length directory.
  • Compression: gzip or brotli for directory and tiles.
  • Zoom levels: from z0 (entire world) to z22 (individual buildings).
  • Maximum size: no theoretical limit (practically tens of GB).

PMTiles vs MBTiles: Comparison

MBTiles is a SQLite database containing tiles. The format appeared earlier and is widely supported, but it has limitations:

Criterion PMTiles MBTiles
Hosting Static (S3, CDN) Requires tile server
Protocol HTTP Range Requests Local SQLite reads
Header size 127 bytes SQLite overhead (~100 KB)
Streaming Yes, any HTTP server No, needs tileserver-gl
Browser support Native (JS library) Only via proxy
Offline on device Limited Good (SQLite is native)

If your goal is offline maps on a mobile device, MBTiles is still more convenient. If you need to serve maps via CDN for a web application, PMTiles wins.

Using with MapLibre GL JS

MapLibre GL JS supports PMTiles through the official plugin:

import { Protocol } from 'pmtiles';
import maplibregl from 'maplibre-gl';

const protocol = new Protocol();
maplibregl.addProtocol('pmtiles', protocol.tile);

const map = new maplibregl.Map({
  container: 'map',
  style: {
    version: 8,
    sources: {
      osm: {
        type: 'vector',
        url: 'pmtiles://https://example.com/map.pmtiles'
      }
    },
    layers: [
      {
        id: 'buildings',
        source: 'osm',
        'source-layer': 'buildings',
        type: 'fill',
        paint: { 'fill-color': '#ccc' }
      }
    ]
  }
});

For Leaflet, the protomaps-leaflet plugin renders vector tiles directly to Canvas.

Exporting PMTiles from OSM

On osm2cdr.ru, select the desired area on the map, choose the PMTiles format, and specify zoom levels. The service will generate a file with vector tiles containing roads, buildings, water bodies, green areas, and other OpenStreetMap layers.

The resulting file can be hosted anywhere:

# Upload to S3
aws s3 cp moscow.pmtiles s3://my-bucket/tiles/ \
  --content-type application/vnd.pmtiles

# Or to Cloudflare R2
wrangler r2 object put tiles/moscow.pmtiles \
  --file moscow.pmtiles

For local viewing, use pmtiles serve:

npx pmtiles serve moscow.pmtiles --port 8080

Conclusion

PMTiles is the future of tile-based maps. One file instead of a tile server, CDN instead of infrastructure, Range Requests instead of millions of small files. Export your OpenStreetMap data to PMTiles at osm2cdr.ru and deploy your own map in 5 minutes.

← All articles