
A few years ago, while advising a large environmental NGO that needed to publish a massive interactive map of deforestation alerts across the Amazon. They had a beautiful frontend, but their traditional PostGIS + GeoServer backend was struggling under unpredictable traffic spikes, and the cloud compute bills were eating into their operational budget.
They asked us to cut costs without sacrificing performance. That’s when we pivoted them entirely to PMTiles.
PMTiles is a single-file archive format for pyramids of tiled data. Rather than running a constantly spinning server that queries a database and spits out vector tiles on the fly, you pre-bake your entire dataset into one .pmtiles file, drop it into a Google Cloud Storage (GCS) bucket, and serve it statically using HTTP Range Requests.
The savings were immediate. We went from hundreds of dollars a month in compute to pennies in storage costs.
Here is the gist of how we converted their GeoJSON into PMTiles using Python (via a wrapper around tippecanoe) and uploaded it:
import subprocess
from google.cloud import storage
# ... (Authentication and setup)
def create_and_upload_pmtiles(geojson_path, bucket_name, output_filename):
"""Converts a GeoJSON to PMTiles and uploads to GCS."""
# 1. First, we use tippecanoe to generate the PMTiles archive
# We use subprocess to call tippecanoe since it's highly optimized in C++
tippecanoe_cmd = [
"tippecanoe",
"-zg",
"--projection=EPSG:4326",
"-o", output_filename,
"-l", "deforestation_alerts",
geojson_path
]
subprocess.run(tippecanoe_cmd, check=True)
print(f"Successfully generated {output_filename}")
# ...
# 2. Upload to Google Cloud Storage
client = storage.Client()
bucket = client.bucket(bucket_name)
blob = bucket.blob(output_filename)
# Ensure CORS is configured on this bucket for HTTP Range Requests!
blob.upload_from_filename(output_filename)
print(f"Uploaded to gs://{bucket_name}/{output_filename}")
# ...
By adding a simple Cache-Control header and exposing the bucket via Google Cloud CDN, their map can now handle a million hits a day without breaking a sweat. If you are serving mostly static or infrequently updated geospatial data, stepping off the map-server treadmill is the best move you can make.
Godspeed!