When you integrate a map into a web app, one architectural decision shapes everything that follows: raster tiles or vector tiles. Get it right and your map is fast, beautiful, and adaptable. Get it wrong and you're shipping a pixelated, sluggish background image that fights your design system at every turn.
This guide explains the technical difference between the two formats, walks through the real-world trade-offs that actually matter to a frontend developer, and gives you a clear decision framework. By the end, you'll know exactly which format to choose for your project and how to get started with vector tiles on MapAtlas.
The tile format question comes up early in almost every mapping project, and the internet is full of surface-level answers that stop at "vector tiles are newer." This guide goes deeper, covering rendering pipelines, payload sizes, browser compatibility, styling control, and the specific scenarios where raster tiles remain the right call.
If you're already building and just need the code, jump to the Quick Start section.

[Image: Side-by-side comparison of the same city block rendered as a raster PNG tile (pixelated at 2x zoom) and a vector tile (crisp at any zoom level), with file size labels showing 180 KB vs 22 KB.]
What Are Raster Tiles?
A raster tile is a pre-rendered PNG or JPEG image, typically 256×256 or 512×512 pixels, representing a fixed slice of the world at a specific zoom level. When a user pans or zooms, the browser requests the adjacent or higher-resolution tiles, which the server has already rendered and cached.
The rendering happens entirely server-side. The tile image that arrives in the browser is a finished picture, pixels are already placed, colors are already baked in. The browser's job is simply to display it.
How raster tile servers work
A raster tile stack typically looks like this:
- Raw geographic data (OpenStreetMap, cadastral data, elevation models) is processed into a database.
- A rendering engine (Mapnik is the classic choice) pre-renders tiles at every zoom level into a tile cache.
- A tile server (TileServer GL in raster mode, or a managed CDN) serves the cached images by
/{zoom}/{x}/{y}.pngURL convention.
The result is simple, fast, and stateless. Any HTTP client can request a tile, a browser, a mobile app, a server-side process generating a map image, or a GIS desktop application.
Raster tile strengths
- Zero client-side rendering overhead. The browser just displays an image. No WebGL required, no shader compilation, no font rendering.
- Universal compatibility. Works in any browser, any version, including Internet Explorer and headless rendering environments.
- Predictable appearance. The map looks exactly as the tile server rendered it. No client-side variability.
- Easy server-side image generation. Perfect for generating static map images for email, PDF reports, or social sharing cards.
Raster tile weaknesses
- Large file sizes. A typical 256×256 PNG tile is 30–200 KB depending on content density. A Retina (512×512) tile is four times the pixel count.
- Pixelation on high-DPI screens. A tile rendered for a 1x display looks blurry on a 2x Retina screen unless you serve @2x tiles, doubling your bandwidth.
- No rotation or tilt. If you rotate a raster map, the text labels rotate with it and become unreadable. This is why raster maps are always north-up.
- No client-side style changes. Want to change the road color, hide POI icons, or switch to dark mode? You need a new tile set, pre-rendered server-side.
- Zoom interpolation. Between integer zoom levels, the browser scales the existing image, which blurs it. The "smooth zoom" feel you get with vector tiles doesn't exist with raster.
What Are Vector Tiles?
A vector tile contains the raw geographic data for a map region, road geometries, building polygons, water bodies, land use areas, label placement data, encoded as compact binary (usually Mapbox Vector Tile format, .mvt). The tile contains no pixels. It describes what exists in that region, not how it should look.
The rendering happens entirely client-side, using WebGL. When you load a Mapbox GL JS-compatible map (like MapAtlas), the SDK requests vector tiles, receives geometry data, and uses your style specification to draw every road, building, and label to a <canvas> element in real time, at 60 frames per second.
How vector tile rendering works
Vector tile (.mvt) + Style JSON → WebGL shader → Canvas pixels
The style JSON (a structured file you control) tells the renderer: draw roads in this color, draw building extrusions at this height, use this font for labels, hide these layer types below zoom 12. The style can be changed at runtime, without fetching new tiles.
Vector tile strengths
- Small payloads. Binary-encoded geometry is far more compact than a rendered image. A typical vector tile for a dense urban area is 15–50 KB versus 80–200 KB for the equivalent raster tile.
- Crisp at any resolution. Vector geometry scales mathematically. A Retina display gets the same tile as a standard display, the renderer simply outputs more pixels. No @2x tile variants needed.
- Smooth zoom and rotation. Because the renderer works on raw geometry, zoom can be interpolated continuously (not just at integer levels) and the map can be pitched and rotated with labels always upright.
- Full client-side style control. Change any visual property, road color, label font, layer visibility, opacity, by updating the style object. No new tile requests. Dark mode is a style JSON swap, not a new tile set.
- 3D building extrusion. Vector tiles include building height metadata. Renderers can extrude polygons in 3D using WebGL. Raster tiles have no concept of elevation.
- Data-driven styling. Color roads by speed limit, shade land use by category, scale markers by population, all driven by data properties in the tile without touching the server.
Vector tile weaknesses
- WebGL required. No WebGL support means no vector tile rendering. This excludes very old browsers (IE11) and certain headless environments.
- Client-side CPU/GPU load. The rendering happens on the user's device. On low-end Android phones or heavily loaded desktops, complex map styles with many layers can cause frame drops.
- More complex initial setup. You need a rendering library (Mapbox GL JS, MapLibre GL, or the MapAtlas SDK) and a style JSON, not just an
<img>tag. - Font and glyph loading. Label rendering requires glyph files to be served separately. This adds a few extra network requests on first load.
Performance Comparison: Real Numbers
To make the trade-off concrete, here are real-world measurements for a map tile of central Amsterdam at zoom level 14:
| Metric | Raster (PNG 512px) | Vector (.mvt) |
|---|---|---|
| Tile size | 142 KB | 31 KB |
| Requests for Retina | 1 (@2x tile) | 1 (same tile) |
| Zoom interpolation | Pixel scaling (blurry) | Mathematical (crisp) |
| Rotation support | No | Yes |
| Style change | New tile request | Zero requests |
| WebGL required | No | Yes |
At scale, vector tiles reduce map-related bandwidth by 60–80%. For a medium-traffic app generating 10 million tile requests per month, that difference meaningfully reduces CDN egress costs.

[Image: Diagram showing the vector tile pipeline: tile server → .mvt binary → WebGL renderer → canvas, with a style JSON feeding into the renderer step. Labels show tile size (28 KB) and render time (8 ms) for a typical urban tile.]
When to Use Raster Tiles
Raster tiles are not obsolete. There are clear scenarios where they remain the right choice:
Legacy system integration. If you're embedding a map in a .NET WebForms app, a server-rendered Rails view, or an environment where you control only HTML and basic JavaScript, a raster tile layer via Leaflet or OpenLayers is simpler and more reliable than introducing a WebGL renderer.
Server-side map image generation. If you need to render map snapshots on a Node.js server for email templates, PDF exports, or open graph images, headless raster rendering is your path. Tools like node-canvas plus a raster tile source work where WebGL does not.
Satellite and aerial imagery. Aerial photography is raster data by nature. Even on a vector map, the satellite imagery layer is always delivered as raster tiles. Hybrid maps mix both formats, vector for roads and labels, raster for the photographic base.
Very simple use cases. Embedding a static location map on a contact page? A simple Leaflet + OpenStreetMap raster setup takes 20 minutes and has zero JavaScript complexity. The upgrade to vector tiles is not justified for a non-interactive location pin.
When to Use Vector Tiles
Choose vector tiles for any modern web application where you care about:
- Custom brand styling. If your design system has specific colors, your map should too. Vector tiles make this a JSON change.
- Dark mode support. A dark style JSON is one configuration file. Switching between light and dark is a
map.setStyle()call. - High-DPI / Retina sharpness. Especially important for mobile-first apps and any UI where crisp rendering is a design priority.
- Smooth user experience. The continuous zoom interpolation and 60fps rendering of a vector map are immediately noticeable to users. Raster maps feel clunky by comparison in interactive contexts.
- Data visualization layers. Adding a heatmap, a choropleth, or a cluster layer to a vector map requires only client-side configuration. On a raster map, you'd tile-blast a new layer or use a canvas overlay hack.
- 3D or tilted perspectives. Only achievable with vector tiles and WebGL.
Quick Start: Vector Tiles with MapAtlas
MapAtlas serves vector tiles via a Mapbox GL JS-compatible API. If you've used Mapbox GL JS before, migration is a style URL change and an API key swap. If you're starting fresh, here's the complete setup.
Install the SDK
npm install @mapmetrics/mapmetrics-gl
Or via CDN for plain HTML projects:
<link rel="stylesheet" href="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css" />
<script src="https://unpkg.com/@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.js"></script>
Render a vector map
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';
const map = new mapmetricsgl.Map({
container: 'map', // ID of your <div>
style: 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY',
center: [4.9041, 52.3676], // [longitude, latitude], Amsterdam
zoom: 12,
pitch: 0, // 0 = top-down, 60 = 3D tilted
bearing: 0, // 0 = north-up, any value = rotated
});
The style URL points to a JSON file hosted on MapAtlas servers that defines all layers, fonts, and sources. You can also host a custom style JSON yourself to control every visual aspect of the map, see the Map Visualization & Styling guide.
Switch to dark mode at runtime
document.getElementById('toggle-dark').addEventListener('click', () => {
const isDark = map.getStyle().name?.includes('dark');
map.setStyle(
isDark
? 'https://tiles.mapatlas.eu/styles/basic/style.json?key=YOUR_API_KEY'
: 'https://tiles.mapatlas.eu/styles/dark/style.json?key=YOUR_API_KEY'
);
});
No new tile requests are triggered for data that's already cached. Only the style changes, the tiles remain the same binary geometry, re-rendered with new colors.
Add a GeoJSON data layer
One of the most powerful vector tile features is overlaying your own data as a styled layer:
map.on('load', () => {
// Add your own data source
map.addSource('delivery-zones', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [[[4.85, 52.34], [4.95, 52.34], [4.95, 52.40], [4.85, 52.40], [4.85, 52.34]]],
},
properties: { zone: 'Zone A', capacity: 150 },
},
],
},
});
// Style it as a colored fill layer
map.addLayer({
id: 'delivery-zones-fill',
type: 'fill',
source: 'delivery-zones',
paint: {
'fill-color': '#97C70A',
'fill-opacity': 0.2,
},
});
map.addLayer({
id: 'delivery-zones-outline',
type: 'line',
source: 'delivery-zones',
paint: {
'line-color': '#97C70A',
'line-width': 2,
},
});
});
This pattern, add a source, add a layer, paint with style expressions, is the same for heatmaps, route lines, isochrone polygons, and choropleth maps. It works because vector tiles give the renderer raw geometry, not finished pixels.
Migrating from Raster to Vector
If you have an existing Leaflet + raster tile setup and want to upgrade, here's the minimal migration path:
- Replace Leaflet with the MapAtlas SDK (or MapLibre GL JS if you prefer a fully open-source renderer).
- Replace the tile URL with a MapAtlas style JSON URL.
- Move overlays from Leaflet layers to GL JS sources and layers.
- Test on WebGL-lacking environments. Add a fallback or graceful degradation message for the small percentage of users who will not have WebGL available.
The functional result is a map that looks sharper, loads faster, and can be restyled without touching the server.
For a full walkthrough of adding markers, popups, address search, and React integration on top of a vector tile base, see How to Add Interactive Maps to Your Website.
To push the styling further, dark mode, brand colors, custom fonts, watermark removal, see How to Style a Custom Branded Map.
And if you're evaluating MapAtlas against Google Maps from a cost and feature standpoint, MapAtlas vs. Google Maps: Why Developers Are Switching covers the key differences.
Summary: The Decision Framework
| Scenario | Recommended format |
|---|---|
| Modern SPA or PWA (React, Vue, Svelte) | Vector tiles |
| Custom brand colors or dark mode | Vector tiles |
| 3D buildings or map tilt/rotation | Vector tiles |
| Data visualization overlays | Vector tiles |
| Legacy browser support (IE11) | Raster tiles |
| Server-side image generation | Raster tiles |
| Satellite/aerial imagery layer | Raster tiles |
| Simple non-interactive location pin | Raster tiles |
If you're building anything interactive in 2026, vector tiles are the default choice. Raster tiles are the deliberate exception for specific compatibility or rendering constraints.
Ready to build with vector tiles? Sign up for a free MapAtlas API key, no credit card required. Your key works across tiles, geocoding, routing, and isochrone APIs from day one.
