◈ GIS Engineering · Vector Tiles · Cloud Architecture

Cloud-Native Web Mapping: PMTiles, Martin & PostGIS

How PMTiles on Cloudflare R2, Rust-powered microservices, and PostGIS optimization are replacing legacy GeoServer stacks and cutting infrastructure costs by up to 90%.

Talha WaheedCo-Founder & Head of Engineering18 min read
Cloud-native geospatial architecture network diagram showing PMTiles, Martin, and PostGIS
← Back to Blog
◈ Executive Technical Summary

Modern cloud-native GIS architectures replace monolithic Java map servers with serverless PMTiles on object storage, Rust-powered Martin tile services, and optimized PostGIS ST_AsMVT vector tile pipelines. This slashes infrastructure costs by up to 90% while delivering sub-50ms tile response times. See this architecture live in our free GeoEditor tool or consult our dedicated technology engineering for PostGIS, GeoServer Modernization, and Mapbox & MapLibre Web GIS.

For almost two decades, Java-based mapping servers like GeoServer and MapServerwere the backbone of web mapping infrastructure. They worked. But "it works" and "it scales economically" are very different things.

The core problem is architectural: every map pan, zoom, and tile request must travel to a centralized application server, spin up JVM threads, negotiate a database connection, execute spatial queries, serialize geometries, and return a payload in real time. Under heavy production load, that pipeline becomes an expensive bottleneck.

Infrastructure Cost Reduction
90%
Sakay production migration benchmark
PMTiles v3 Initial Payload
16 KB
97% reduction vs v2 (512 KB)
PostGIS Polygon Speedup
87%
CARTO ST_AsMVTGeom benchmark
JVM Garbage Collection Stalls
0 ms
Rust / Go native compilation

Why Monolithic GIS Servers Are Failing Modern Applications

GeoServer deployments require deliberate JVM memory configuration. Its official production guidance documents heap sizing, garbage collection, and related Java settings that add state and capacity planning to an otherwise elastic cloud deployment.

JVM ParameterFunctionScalability Impact
-XmsInitial heap size on startupWastes idle cloud resources if set too high
-XmxMaximum memory allocation poolLimits concurrent tile rendering threads
-XX:MaxPermSizeClass bytecode storage (PermGen)Exhaustion causes catastrophic server crashes
Diagram showing monolithic GIS server pipeline

Cloud-Native Geospatial Formats: The Foundation

The paradigm shift does not just replace one server with a faster one. It removes the server entirely for the majority of use cases, leveraging a class of cloud-native file formats built around HTTP range requests.

Legacy Format
Shapefile / MBTiles

Requires local file downloads or running database middleware to extract geometry.

Cloud-Native Format
PMTiles / GeoParquet

Clients query only specific byte ranges directly from standard S3/R2 storage with zero compute.

The OGC Cloud Optimized GeoTIFF standard established this methodology for raster data. The GeoParquet specification brings interoperable geospatial types to columnar analytics, while FlatGeobuf documents its HTTP range-request and spatial-indexing model.

PMTiles: The Gold Standard for Static Map Delivery

For spatial data with update cycles measured in days, weeks, or months, PMTiles is the premier static delivery mechanism. The PMTiles v3 specification defines a single-file tile archive whose directories and tile payloads can be retrieved with HTTP range requests, completely bypassing tile servers.

⬡ Hilbert Curve Addressing in PMTiles v3

PMTiles v3 replaces older Z/X/Y directory structures with 64-bit Hilbert Curve ordering. Geographically adjacent tiles map to contiguous byte sequences, maximizing CDN cache locality and shrinking initial directory requests to 16 KB.

Hilbert curve tile ordering in PMTiles v3

Infrastructure Economics: Escaping the Egress Trap

PMTiles’ technical brilliance only matters if you can serve it economically at scale. Traditional hyperscale cloud providers charge punishing egress fees on high-traffic range queries.

The Cloudflare R2 Advantage

Cloudflare R2 provides zero-egress fee object storage. In production case studies like Sakay, migrating map basemaps to PMTiles on Cloudflare R2 resulted in documented 90% cost reductions.

Dynamic Data: Rust-Powered Vector Tile Microservices (Martin)

When data updates in real time, static PMTiles are paired with dynamic tile servers. Martin, written in Rust and maintained under the MapLibre organization, generates vector tiles directly from PostGIS functions with zero JVM overhead.

# Martin configuration (config.yaml)
postgres:
  connection_string: 'postgresql://postgres:secret@db.internal:5432/spatial_db'
  auto_publish:
    tables:
      from_schema: 'public'
    functions:
      from_schema: 'public'

pmtiles:
  sources:
    basemap: '/data/planet.pmtiles'

PostGIS Optimization: The ST_AsMVT Pipeline & Dynamic LOD

PostGIS aggregates binary Mapbox Vector Tiles using ST_AsMVT() and transforms planar geometry into screen-space tile coordinates with ST_AsMVTGeom().

However, querying full-resolution geometries at low zoom levels produces multi-megabyte MVT payloads that choke network bandwidth and exhaust client WebGL memory. Production pipelines implement Zoom-Dependent Level of Detail (LOD) using ST_SimplifyPreserveTopology() with dynamic pixel tolerance:

-- Martin Custom Function: Generates optimized vector tiles with dynamic LOD
CREATE OR REPLACE FUNCTION public.get_parcels_tile(
  z integer, x integer, y integer
) RETURNS bytea AS $$
DECLARE
  tile_bbox geometry;
  pixel_tolerance float8;
  result bytea;
BEGIN
  -- Generate EPSG:3857 bounding box for current tile
  tile_bbox := ST_TileEnvelope(z, x, y);
  
  -- Calculate meters per pixel at this zoom level (Web Mercator)
  pixel_tolerance := (40075016.68 / (256 * (2 ^ z))) * 0.5;

  WITH mvt_data AS (
    SELECT
      ST_AsMVTGeom(
        -- Simplify vertex density to pixel resolution; preserve topology
        ST_SimplifyPreserveTopology(geom, pixel_tolerance),
        tile_bbox,
        4096, 64, true
      ) AS mvt_geom,
      id,
      name,
      -- Omit granular property attributes at coarse zooms to minimize byte weight
      CASE WHEN z >= 14 THEN parcel_type ELSE NULL END AS parcel_type,
      CASE WHEN z >= 14 THEN assessed_value ELSE NULL END AS assessed_value
    FROM parcels
    WHERE geom && tile_bbox
      -- Filter out micro-polygons smaller than 4 screen pixels at current zoom
      AND (z >= 14 OR ST_Area(geom) > (pixel_tolerance * pixel_tolerance * 4))
  )
  SELECT ST_AsMVT(mvt_data.*, 'parcels', 4096, 'mvt_geom')
  INTO result
  FROM mvt_data
  WHERE mvt_geom IS NOT NULL;

  RETURN result;
END;
$$ LANGUAGE plpgsql STABLE PARALLEL SAFE;

Architecture Comparison: Legacy vs. Cloud-Native

Modern web mapping replaces bloated monolithic servers with lightweight, single-purpose primitives:

Metric / FeatureGeoServer (Java / WMS)Martin (Rust / MVT)PMTiles on Cloudflare R2
Runtime Footprint2–4 GB (JVM Heap)20–30 MB (Native Rust)0 MB (Serverless Object Storage)
P99 Tile Latency180–450 ms8–25 ms15–35 ms (Edge CDN)
GC Stalls / PausesFrequent (JVM Stop-the-World)Zero (Rust zero-cost memory)Zero (Static Byte Ranges)
Data FreshnessReal-timeReal-time (PostGIS SQL)Static / Periodic Pipeline Build
Cost per 10M Requests$180–$400/mo (EC2 Clusters)$25–$50/mo (Small VM)$3.60/mo (R2 Class B Ops)

Multi-Tiered Caching: The Final Performance Layer

Vector tile URLs are completely deterministic. Modern pipelines deploy multi-tier caching across CDN edges, Nginx reverse proxies, and Martin's internal memory cache.

Multi-tier caching architecture from CDN to PostGIS

Frequently Asked Questions

What is PMTiles v3 and how does it eliminate web mapping tile servers?

PMTiles v3 is a single-file archive format for pyramids of tiled data (vector, raster, or elevation). It uses a 127-byte header and a 64-bit Hilbert Curve addressing directory. Web clients like MapLibre GL JS issue HTTP Range requests directly to cloud object storage (e.g., Cloudflare R2 or AWS S3), fetching only the necessary 16KB directory sector and the exact tile byte slice without requiring an active tile application server.

Why is Cloudflare R2 favored over Amazon S3 for hosting PMTiles archives?

Web maps generate massive volumes of HTTP Range requests as users pan and zoom across viewports. Traditional hyperscale cloud providers charge $0.09 per GB in outbound data egress fees, which causes serverless mapping bills to escalate unpredictably. Cloudflare R2 provides S3-compatible object storage with $0 egress fees, enabling high-traffic vector tile streaming at a fraction of the cost.

How does Martin (Rust) outperform GeoServer or pg_tileserv for dynamic vector tiles?

Martin is compiled to native machine code in Rust with an asynchronous Tokio runtime, operating with a memory footprint of just 20-30 MB and zero JVM garbage collection stalls. Compared to legacy Java-based GeoServer stacks (which require 2-4 GB heap space and suffer GC pauses), Martin achieves sub-10ms P99 tile generation latencies and seamlessly multiplexes PostGIS functions with static PMTiles archives.

How do you prevent MVT tile size bloat in PostGIS queries?

To avoid generating multi-megabyte MVT tiles that crash WebGL contexts at low zoom levels, use zoom-scaled geometry simplification via ST_SimplifyPreserveTopology(geom, tolerance) where tolerance is scaled to pixel dimensions, filter out minor polygons using ST_Area(geom) < zoom_threshold, and omit granular attributes that are only needed at detailed inspection zooms.

Ready to Modernize Your Spatial Architecture?

Migrate from Legacy GIS Servers to Cloud-Native

Infryne TechWorks builds modern geospatial infrastructure for teams moving off bloated GIS servers: PMTiles deployment, Martin configuration, and PostGIS optimization.

Primary Sources & Datasets

Continue Reading

More engineering research from Infryne TechWorks