MapProxy vs TileServer GL for Tile Delivery

Picking the wrong tile server locks a portal into the wrong data model: choose a raster cache when you needed client-side vector styling, or a vector server when your sources are heterogeneous WMS endpoints, and you pay for it in CPU, bandwidth, and re-platforming. This guide compares MapProxy and TileServer GL as tile-delivery engines so platform teams can commit to the right one before the traffic arrives.

This comparison sits within the Infrastructure Orchestration & Configuration Management practice and pairs a decision framework with a concrete hybrid topology. It weighs the two servers on their tile model, source flexibility, reprojection and grid support, styling, caching, client stack, and scaling profile — the axes that actually decide which one survives production.

MapProxy raster-caching path versus TileServer GL vector-tile path On the left, MapProxy sits between heterogeneous upstream WMS and WMTS services and raster clients. It reprojects and pre-renders image tiles into a shared cache backend, then a load balancer fans PNG and JPEG tiles out to OpenLayers and Leaflet clients that render server-styled images. On the right, TileServer GL reads a vector MBTiles or PMTiles archive, serves Mapbox Vector Tiles from a stateless process, and a MapLibre GL client downloads the vector tiles plus a style JSON and renders and styles them on the GPU in the browser. MAPPROXY · PRE-RENDERED RASTER TILESERVER GL · VECTOR (MVT) Any WMS / WMTSheterogeneous sources MapProxyreproject · pre-render Tile cacheS3 · Redis · files Raster clientOpenLayers · Leaflet PNG / JPEG styled image MBTiles / PMTilesvector archive TileServer GLserve MVT · stateless MapLibre GL clientGPU render + style style.jsonGL style spec vector tiles MVT + style

The core split: pre-rendered rasters vs client-side vectors

Everything downstream follows from one architectural choice — where the map is drawn. MapProxy is a raster-first engine: it fetches map images from upstream OGC services, optionally reprojects and re-tiles them, and stores the finished pixels in a cache. What the browser receives is a completed PNG or JPEG; the server did the drawing. That model is decades-proven, trivially cacheable at every layer, and completely agnostic to how capable the client device is, because the client only ever paints images onto a grid.

TileServer GL inverts that. It serves Mapbox Vector Tiles (MVT) — compact, quantized geometry with feature attributes — and defers rendering to the client. A MapLibre GL browser downloads the vector tiles plus a style JSON and rasterizes them on the GPU in real time. The same tile can be restyled, relabeled, rotated, tilted, or filtered without a single new request to the server, because styling is a client concern decoupled from data delivery. The cost is a heavier, WebGL-dependent client and a data pipeline that must produce vector tiles in the first place.

The practical consequence is that these two servers answer different questions. MapProxy answers “how do I put existing raster and WMS layers in front of many clients, fast, in whatever projection they need?” TileServer GL answers “how do I ship one compact vector dataset that many differently-styled, interactive maps can render themselves?” Confusing the two leads to either re-rendering raster tiles you could have cached once, or shipping raster images where you wanted live restyling.

Source flexibility and the data pipeline

MapProxy’s headline strength is source promiscuity. It will front any WMS, WMTS, TMS, or Mapbox-style raster source, cascade several of them behind one endpoint, and merge or clip layers on the way through. This is exactly why it slots so naturally in front of a GeoServer or a fleet of legacy agency WMS services — you point it at what already exists. It is also why it appears in the portal architecture comparison at GeoNode vs MapProxy Architecture Comparison: it is a caching data plane, not a data producer.

TileServer GL is narrower by design. It serves vector (and raster) tiles out of MBTiles or PMTiles archives — it does not proxy a live WMS. That means an upstream build step: you generate vector tiles with a tool such as tippecanoe or planetiler, package them into an .mbtiles or .pmtiles file, and hand that immutable artifact to the server. The trade is real. TileServer GL loses the “point it at anything” flexibility but gains a reproducible, versionable data artifact that is a single file, cache-friendly at the CDN, and cheap to replicate to every stateless replica.

Dimension MapProxy TileServer GL
Primary tile model Pre-rendered raster (PNG/JPEG) Vector tiles (MVT), rendered client-side
Upstream sources Any WMS / WMTS / TMS, cascaded MBTiles / PMTiles archive (pre-built)
Reprojection On the fly, arbitrary EPSG grids None at serve time; bake grid at build
Styling model Baked into cached image GL style JSON, restyled in the client
Data pipeline Point at existing services tippecanoe / planetiler build step
Native client OpenLayers, Leaflet (raster) MapLibre GL (WebGL)
CPU cost Reprojection + rendering on miss Low server CPU; work moves to client GPU
Bandwidth Larger images, many per view Compact tiles, restyle without refetch
Statefulness Cache only (disposable) Read-only archive (immutable)

Reprojection and tile grids

Reprojection is where the two diverge most sharply, and it is the axis that most often forces the decision. MapProxy is a genuine reprojection engine: it can take a source in one CRS and serve it in another, aligning output to arbitrary tile grids and OGC well-known scale sets on the fly. If your clients demand EPSG:25832, EPSG:3035, and Web Mercator from the same source, MapProxy handles it as a first-class feature, and grid alignment stays compliant with the OGC WMTS specification so heterogeneous clients see consistent tile boundaries.

TileServer GL does no serve-time reprojection. Vector tiles are effectively locked to the Web Mercator (EPSG:3857) grid baked in at build time by the tiling tool. For the overwhelming majority of web-mapping workloads that is exactly what you want and it is why the ecosystem standardized on it — but if your mandate includes national grids or polar projections, that constraint is disqualifying on its own. The rule of thumb: multi-projection or legacy-CRS requirements point at MapProxy; Web-Mercator-only interactive maps point at TileServer GL.

Styling: server-baked pixels vs the GL style spec

With MapProxy, styling lives upstream. The WMS source decides the cartography, MapProxy caches the resulting image, and changing the look means re-rendering and re-seeding the cache. That is a strength when the styling is authoritative and rarely changes — a cadastral basemap looks identical to every client, forever, with zero client compute.

TileServer GL exposes the full MapLibre GL style specification. One vector tile set can drive a light theme, a dark theme, a print theme, and a data-driven choropleth simultaneously, each defined in a JSON style document and switched instantly in the browser. Interactive features — hover states, zoom-dependent labels, feature filtering, 3D extrusion — become client configuration rather than server round-trips. When the product requirement is rich, interactive, restyleable cartography, this is decisive; the MapLibre documentation is the reference for the style spec and GL client.

Caching, seeding, and delivery

Both servers cache, but they cache different things. MapProxy’s cache is a warmable store of finished tiles: you pre-seed hot extents so the first user of a busy area never triggers an expensive upstream render, and you back the cache with S3 or Redis so a fleet of stateless replicas shares warmth. Seeding is an operational lever you schedule and tune; the MapProxy documentation covers seed configuration and cache backends in depth.

TileServer GL’s “cache” is upstream of the process: because the MBTiles/PMTiles archive is immutable, the whole delivery path is aggressively cacheable at a CDN with long TTLs and content-hashed URLs. There is no seeding step because there is no rendering-on-miss — the tiles already exist in the archive. In both cases the server should sit behind the same hardened reverse proxy tier described in Reverse Proxy Configuration for WMS/WFS, which terminates TLS, applies rate limits, and caches GetCapabilities-style metadata at the edge.

Scaling and CPU/bandwidth profile

The scaling stories differ in where the work lands. MapProxy spends server CPU on reprojection and rendering at cache-miss time and pushes larger raster payloads over the wire; you scale it by adding stateless workers behind a load balancer and by widening the shared cache so misses are rare. TileServer GL spends very little server CPU — it is essentially reading a file and streaming compact tiles — but it moves rendering cost onto the client GPU and assumes a capable browser. Its replicas are trivially horizontal because the archive is read-only, which makes it an easy fit for the high-availability container pattern in Containerizing TileServer GL for High Availability.

To ground these trade-offs in numbers for your own layers and hardware, do not trust vendor claims — measure. The companion page Benchmarking Tile Latency with k6 walks through a load test that drives randomized tiles at both servers and reports p95/p99 latency for cache-cold and cache-warm runs, which is the only honest way to size either tier.

When MapProxy fits

Reach for MapProxy when the sources you must serve are existing WMS/WMTS services and you cannot or will not rebuild them into vector tiles; when clients need multiple projections or non-Mercator grids; when the cartography is authoritative and server-baked rasters are acceptable; and when you want a caching layer that fronts a GeoServer to absorb read traffic without touching the database. Government and agency portals with heterogeneous legacy raster catalogs are the archetype — MapProxy meets the data where it already lives.

When TileServer GL fits

Reach for TileServer GL when the product is an interactive, restyleable web map on Web Mercator; when you can run a tiling build step to produce a versioned MBTiles/PMTiles artifact; when bandwidth and client interactivity matter more than server-side projection flexibility; and when you want dead-simple, immutable, horizontally trivial replicas. Modern public-facing basemaps, data-exploration dashboards, and anything that needs light/dark themes or client-side filtering are the archetype — the vector model pays for its build step many times over.

A hybrid delivery topology

The mature answer is frequently both, split by layer type rather than chosen wholesale. Serve interactive, Web-Mercator vector layers — basemaps, points of interest, boundaries the user filters and restyles — from TileServer GL, and serve authoritative or multi-projection raster layers — orthoimagery, scanned maps, legacy agency WMS — from MapProxy. A single reverse proxy fronts both under one origin so the browser sees a coherent API, and both tiers share the same load balancer, TLS termination, rate limiting, and observability. This mirrors the general split articulated in the portal architecture comparison: a stateless, read-optimized delivery plane, composed here of two specialized servers each doing what it is best at, in front of the same governed data core.

Recommendation

Do not treat this as a single global choice. Classify each layer by projection need, styling need, and whether a vector build step is feasible, then route it to the server that matches. If you can only run one, let the dominant requirement decide: multi-projection or live-WMS fronting means MapProxy; interactive Web-Mercator cartography with a build pipeline means TileServer GL. Whichever you pick, set scaling thresholds from measured latency under representative load rather than defaults, and keep the delivery tier stateless so it scales independently of the metadata and write path.

Up one level: Infrastructure Orchestration & Configuration Management.