Coordinately

Tile Servers and Caching Explained

Tile servers deliver map tiles over HTTP. Architectures include pre-generated static tiles served from a CDN (cheap, immutable), on-demand rendering from a database (flexible, expensive at scale), and hybrid render-and-cache approaches. Major tile servers: TileServer GL, Tegola, Martin, pg_tileserv, GeoServer, Mapnik via mod_tile, MapTiler Server. Caching strategies span browser → CDN edge → CDN regional → origin tile server, with hit rates typically 95%+. Pricing varies from ~$0.50-2 per 1,000 requests commercial to free self-hosted with operational cost. The article covers architectures, caching tiers, cost models, and operational considerations including bot scraping and DDoS mitigation.

By . Published . Last updated .

This article closes the recommended trio of Web Mapping & Tile Systems supports with the operational considerations behind tile delivery. Companion to /learn/slippy-map-tiles-explained and /learn/vector-tiles-explained.

What a tile server does

A tile server is an HTTP server that accepts requests for tiles and returns the tile data:

GET /v1/tiles/streets/14/4825/6155.pbf
→ 200 OK
   Content-Type: application/x-protobuf
   Content-Encoding: gzip
   Cache-Control: public, max-age=31536000
   [vector tile bytes]

The server's job: figure out what to send for any given (style, Z, X, Y) request, and send it efficiently. The complexity lies in:

  1. Where the tile data comes from (pre-generated storage vs on-demand rendering from a database).
  2. How tiles are cached at multiple tiers.
  3. How the server scales to handle traffic.
  4. How costs are controlled (storage, bandwidth, compute).

Three server architectures

Pre-generated static tiles

Tiles are rendered in advance, stored as files, and served by a static HTTP server (Nginx, S3, CDN origin). The flow:

  1. Run a one-time rendering job to generate every tile in the pyramid.
  2. Upload tiles to S3 / Cloudflare R2 / Backblaze B2 / etc.
  3. Configure CDN to serve from the storage origin.
  4. Maps load tiles from the CDN; the renderer is no longer involved.

Advantages:

  • Trivially scalable — CDN handles all traffic.
  • Low marginal cost per request.
  • Simple operations — no server-side process to manage.
  • No DDoS surface — CDN absorbs traffic naturally.

Disadvantages:

  • Large storage: a global zoom-18 raster tile set is terabytes; a zoom-22 set is petabytes. Vector tiles are smaller but still significant.
  • Slow updates: regenerating tiles takes hours to days; data updates aren't immediate.
  • No dynamic queries: every tile is identical for all users.

On-demand rendering

Tiles are generated when requested, from a PostgreSQL database (typically PostGIS) or other source. The flow:

  1. Source data lives in the database.
  2. Tile server receives request, executes a database query.
  3. Server renders the result into a tile.
  4. Server returns the tile.

Servers in this category: Martin (Rust), pg_tileserv (Go), Tegola (Go), GeoServer (Java), TileServer GL (Node.js, with various backends).

Advantages:

  • Tiny storage — just the source database.
  • Always fresh — data updates appear immediately.
  • Supports dynamic queries — different tiles for different users / parameters.

Disadvantages:

  • CPU/RAM cost per request — rendering takes compute.
  • Database load — every cache miss hits the DB.
  • Query-pattern DDoS — an adversary requesting many distinct expensive tiles can overload.
  • Caching layer essential for any scale.

Hybrid render-and-cache

The OSM approach. Mapnik renders tiles on-demand into a disk cache; subsequent requests for the same tile come from cache.

Mod_tile (Apache module developed by OSM) is the classic implementation:

  1. Request arrives.
  2. mod_tile checks if the tile file exists in cache.
  3. If yes: serve from cache.
  4. If no: render via Mapnik, save to cache, serve.
  5. CDN sits in front for further caching.

The hybrid approach balances:

  • Lower storage than pre-generated (tiles generated only where requested).
  • Faster than pure on-demand (popular tiles cached on disk after first request).
  • Operational complexity between the two extremes.

OSM's tile.openstreetmap.org runs this architecture, serving billions of tile requests per day with a relatively small render farm.

Major tile servers

TileServer GL

Open-source server for vector tiles (MapTiler). Renders Mapbox Vector Tile sources with the Mapbox Style Specification. Can also serve pre-rendered raster tiles. Used by many self-hosted setups.

Tegola

Go-based open-source server for vector tiles. Reads from PostGIS, GeoPackage, or files. Generates MVT tiles on-the-fly. Fast (Go is well-suited to high- throughput tile generation).

Martin

Rust-based open-source vector-tile server. PostgreSQL/PostGIS focus. Very fast, low memory footprint. Gaining popularity for production deployments.

pg_tileserv

Go-based open-source vector tile server developed by Crunchy Data. PostgreSQL-only, simple configuration. Good for moderate-scale PostGIS-backed services.

GeoServer

Java-based, comprehensive OGC-standards server. Supports WMS, WMTS, WFS, WCS, vector tiles, and more. Heavyweight; rich administrative UI. Common in government and enterprise GIS deployments.

Mapnik / mod_tile

The OSM rendering pipeline. Mapnik is a C++/Python library for rendering raster tiles from PostGIS; mod_tile is the Apache module that wraps it for tile delivery with caching. Used by OSM.org and many OSM-based projects.

MapTiler Server

Commercial integrated tile server from MapTiler. Includes administrative UI, multiple data formats, auto-scaling. Used by Coordinately's base map.

Cloud-based managed services

  • Mapbox: hosted commercial.
  • MapTiler: hosted commercial.
  • Stadia Maps: hosted commercial.
  • Stamen Design: hosted (now via Stadia).
  • Google Maps Platform: hosted commercial.
  • HERE Technologies: hosted commercial.

Caching strategies

Cache tiers

The full cache hierarchy:

User → Browser cache → CDN edge (regional) → CDN regional (multi-region) → Origin tile server

Each tier responds with cached data if available. Only true cache misses propagate up to origin.

Cache hit rates

For a typical production map:

  • Browser cache hit rate: ~30-50% (same user re-visiting same tiles).
  • CDN edge cache hit rate: ~95-99% (popular tiles served from edge).
  • Overall origin hit rate: ~1-5% (only true misses).

Long-tail consideration: ~80% of tile requests hit ~20% of tiles (Pareto-like). Popular city center tiles get millions of requests each; remote ocean tiles get tens.

HTTP caching headers

Standard headers control cache behavior:

Cache-Control: public, max-age=31536000, immutable
ETag: "abc123"
Last-Modified: Mon, 25 May 2026 17:30:00 GMT
  • max-age=31536000 (1 year) is common for immutable tiles.
  • ETag allows conditional requests (304 Not Modified responses).
  • Last-Modified allows If-Modified-Since validation.

The immutable directive tells caches the response will never change — eliminating revalidation requests.

CDN configurations

Common CDN choices:

  • CloudFront: AWS's CDN. Tight integration with S3. ~200 edge locations. Range-request support for PMTiles.
  • Cloudflare: free tier available; global edge network. Cloudflare Workers can add dynamic per-request logic.
  • Fastly: developer-favorite. Powerful VCL config language; rapid cache invalidation.
  • Akamai: enterprise; legacy customers.

For tile delivery, CDN choice typically depends on existing infrastructure relationships and cost optimization.

Cache invalidation

When source data changes, cached tiles become stale. Strategies:

  • Wait for natural expiration: relies on tiles having low max-age. Acceptable for daily-updated data.
  • CDN purge by URL pattern: invalidate specific tile ranges. CDN-vendor-specific cost (~$0.005-0.05 per invalidation in some CDNs).
  • Cache versioning: include a version in the URL path (/v2/tiles/...); old cached tiles age out without invalidation. Most common for production.
  • Tile-key-based invalidation: tools like Apache Traffic Server or specialized vendors offer fine-grained pattern-based purge.

HTTP/2 and HTTP/3

Tile delivery benefits from modern HTTP versions:

HTTP/1.1

Each tile is a separate request; browsers limit concurrent connections to ~6 per origin. Loading 20 tiles requires sequential rounds.

HTTP/2

Multiplexing: all tile requests share a single connection. Browsers can issue many simultaneous tile requests without round-trip overhead. Loading 20 tiles is roughly the time of 1-2 tiles. Standard since ~2015 across all major browsers and CDNs.

HTTP/3 (QUIC)

UDP-based with built-in TLS. Lower head-of-line blocking — a slow tile doesn't block faster tiles behind it on the same connection. Particularly helpful on flaky networks (mobile, satellite). Now widely supported by CloudFront, Cloudflare, and major browsers since 2022.

For tile delivery: HTTP/2 is the practical default; HTTP/3 adds meaningful improvement on mobile and international connections.

Cost modeling

Storage cost

Global tile pyramid sizes (rough):

| Zoom range | Raster (PNG) | Vector (MVT) | | ---------- | ------------ | ------------ | | 0-10 | ~100 GB | ~10 GB | | 0-14 | ~5 TB | ~500 GB | | 0-18 | ~50 TB | ~5 TB | | 0-22 | ~petabytes | ~50 TB |

Pre-generating zoom 0-18 globally is feasible (~$1,000- 10,000/month at AWS S3 rates). Zoom 0-22 is generally not.

Bandwidth cost

Per-tile bandwidth times request volume. Per-tile typical sizes:

  • Raster tile: 5-50 KB (average 15 KB).
  • Vector tile: 5-100 KB (average 25 KB after gzip).

For 10 million tile requests/month at 25 KB average: ~250 GB transfer ≈ $20-30/month at typical CDN pricing.

Compute cost

For on-demand rendering: each tile costs CPU time. Order of magnitude: ~1-10 ms per tile on modern hardware (varies wildly by complexity). A small VM ($50/month) can render ~10-100M tiles/month if cache hits dominate.

Commercial pricing

| Provider | Free tier | Per-1k pricing | | -------- | --------- | -------------- | | Mapbox | 50,000/month | $0.50 raster / $0.40 vector | | MapTiler | varies by plan | similar | | Google Maps | $200/month credit | varies by API |

Commercial providers price tiles to recover infrastructure costs plus margin. Self-hosting can be cheaper at scale but requires operational expertise.

OpenStreetMap tile usage policy

OSM provides free tiles at tile.openstreetmap.org but restricts free use to preserve the service for the community:

Acceptable use

  • Small-scale websites and applications.
  • Educational projects.
  • Personal hobby maps.
  • Maximum reasonable bandwidth (typically <100 GB/month per IP).
  • Clearly visible attribution.

Not acceptable

  • High-traffic commercial sites.
  • Production applications without arrangement.
  • Hot-linking from competing services.
  • Automated scraping (download all tiles for a region).
  • No-attribution use.

Enforcement

The OSM operations team monitors usage. Violators face IP-level rate limiting or blocking. Persistent violators may be permanently excluded.

Compliant alternatives

For commercial or high-traffic use:

  • Commercial providers: Mapbox, MapTiler, Stadia Maps, others — pay-per-use with operational SLAs.
  • Self-hosting: install Mapnik + mod_tile + PostGIS + OSM data; serve your own tiles. Switch2OSM (switch2osm.org) provides setup documentation.
  • Hybrid: cache OSM tiles via your own CDN (still need to respect OSM's policy on origin fetching).

Operational issues

Bot scraping

Scrapers can download many tiles in parallel, costing bandwidth and compute. Mitigations:

  • Rate limiting per IP / API key.
  • CDN bot detection (Cloudflare bot management, AWS WAF bot rules).
  • Referer header check (deny without valid referer).
  • API token authentication (commercial providers).

DDoS

Tile traffic naturally spikes (e.g., a high-traffic webpage embedding a tile map). To distinguish legitimate spikes from DDoS:

  • CDN DDoS protection (CloudFront Shield, Cloudflare DDoS protection).
  • Geographic rate-limiting.
  • Request-pattern analysis (high-cost queries detected and throttled).

Cost explosions

A poorly-coded client (refetching the same tile every frame, infinite zoom, etc.) can cause bill spikes. Mitigations:

  • Per-user usage limits at the API tier.
  • CDN cost alerts.
  • Origin request limits (max requests/second to origin).

Tile data quality

Source data may have bugs, missing features, or controversial labels. Updates are needed periodically; cache invalidation strategy must support them.

Self-hosting overview

For projects that want self-hosted tile delivery, the typical stack:

  1. OSM data: download from download.geofabrik.de or planet.openstreetmap.org.
  2. PostgreSQL + PostGIS: import OSM data via osm2pgsql.
  3. Tile generator:
    • Mapnik + mod_tile for raster.
    • Tegola / Martin / Tippecanoe for vector.
    • OpenMapTiles workflow for full vector pipeline.
  4. Caching layer: CloudFront / Cloudflare / Nginx reverse proxy.
  5. Update workflow: periodic OSM extract download
    • database update + tile-cache invalidation.

Setup time: 2-10 days for production-ready self-hosting. Ongoing operations: ~few hours/week for data updates.

Common misconceptions

“Tile servers are simple.” Surface-level yes, but caching, performance tuning, and operational management at scale are non-trivial.

“CDN caching is free.” CDN bandwidth and request costs are real and can exceed origin compute costs at scale. Optimization matters.

“The OSM tiles are unlimited.” They're free for small-scale use only. Violating the policy gets you blocked.

“Pre-generation is always cheaper.” Pre-generation is cheap per request but expensive in storage and regeneration. For low- traffic services, on-demand is cheaper overall.

“Caching invalidation is instant.” Cache invalidation propagation takes seconds to minutes across global CDN edges. Plan for this delay in any data-update workflow.

“You need WebGL for any modern map.” For vector tiles yes; for raster tiles no. Many legacy maps and accessibility-conscious sites still use raster.

“HTTP/3 is required.” HTTP/2 is sufficient for nearly all use cases; HTTP/3 adds incremental improvement. Don't block on HTTP/3 support.

“Self-hosting OSM tiles is hard.” Moderate complexity — there are mature stacks (Switch2OSM, OpenMapTiles) with good documentation. A capable engineer can have it running in a day. Operating it long-term takes care but isn't heroic.

“CloudFront is the cheapest CDN.” Depends on usage. CloudFront is competitive with S3-origin integration; Cloudflare has stronger free tier; Fastly has more advanced features. Compare based on actual traffic patterns.

“Vector tiles eliminate the need for tile servers.” PMTiles can — for some use cases. But most production systems still use tile servers for dynamic content, authentication, usage tracking, and operational control.

“Map providers' pricing is predictable.” Cost spikes happen — a viral webpage embedding your map can produce 100× normal traffic in a day. Budget for surprises and set up usage alerts.

“You don't need attribution.” You do — all open and commercial providers require attribution. OSM, MapBox, MapTiler, Google all have specific attribution requirements; the MapLibre default attribution control (bottom-right) usually suffices. See Coordinately's arch decisions (§19.3) for the MapTiler attribution requirement.

“Stale tiles aren't a problem.” Stale tiles can show outdated features (closed roads, demolished buildings) — confusing to users and potentially dangerous for navigation. Establish cache-update SLAs based on your data's rate of change.

Frequently asked questions

What is a tile server?

A tile server is an HTTP server that delivers map tiles. It accepts requests like GET /Z/X/Y.png (or .pbf for vector tiles) and returns the tile data. The server may pre-generate tiles in advance (static delivery from disk or CDN), render tiles on-demand from a database, or use a hybrid (render-and-cache on first request, subsequent requests from cache). Major tile servers: TileServer GL (Mapbox), Tegola (Go-based vector tiles), Martin (Rust-based PostGIS vector tiles), pg_tileserv (Go-based PostGIS), GeoServer (Java-based, OGC standards-heavy), Mapnik via mod_tile (the OSM renderer pipeline), MapTiler Server (commercial integrated). The choice depends on data source, vector vs raster, performance requirements, and licensing.

How does tile caching work?

Tiles are cached at multiple tiers between origin and client, dramatically reducing load on tile-generation infrastructure. The standard hierarchy: browser cache (the user's local cache — first request hits the network, subsequent same-tile requests are local). CDN edge cache (CloudFront, Cloudflare, Fastly — typically dozens to hundreds of edge locations globally; ~95% hit rate for popular tiles). CDN regional cache (mid-tier cache shared across edges in a region). Origin tile server (the actual renderer or storage). Each tier responds with cached data if available; only true cache misses propagate to origin. Cache headers (Cache-Control, ETag, Last-Modified) control behavior; max-age=31536000 (1 year) is typical for immutable tiles.

Pre-generated vs on-demand tiles — which is better?

Pre-generated (static) tiles: generate every tile in advance, store as files (S3 + CloudFront, Nginx serving disk files, etc.). Pros: cheap per-request, simple architecture, scales horizontally trivially. Cons: storage cost (global zoom-22 set is petabytes), regeneration on data update is expensive, doesn't support dynamic queries. On-demand: render tiles from a database when requested. Pros: tiny storage (just the source data), data freshness, can serve dynamic queries. Cons: rendering cost per request, complex caching needed to scale, vulnerable to query-pattern DDoS. Hybrid (render-on-miss, cache result): Render the first time a tile is requested, cache the result on disk/CDN, serve from cache thereafter. Used by OSM tile.openstreetmap.org via mod_tile. Best of both worlds for moderate-traffic services.

What does tile delivery cost?

Costs vary by approach. Commercial providers: Mapbox $0.50-2 per 1,000 requests above free tier; MapTiler similar; Google Maps free tier then per-1000 pricing. CDN-served pre-generated tiles: storage ($0.02/GB-month S3) + bandwidth ($0.085/GB CloudFront in US) + request ($0.0075 per 10K HTTPS requests CloudFront). A 1 TB tile set at modest 10M requests/month: ~$20 storage + ~$100 bandwidth + ~$10 requests = ~$130/month. On-demand rendering: dominated by compute cost. A Tegola or Martin instance on a $50/month VM can serve millions of requests/month for free of marginal cost. Self-hosted from OSM is essentially infrastructure-cost-only after the OSM-data download. The 'right' choice depends on traffic volume and budget.

What is the OSM tile usage policy?

The OpenStreetMap Foundation operates tile.openstreetmap.org as a free service but limits its use to small-scale applications. Heavy usage (high-traffic sites, commercial applications, production systems) is expected to either self-host OSM tiles or use a commercial provider. The policy specifies: maximum reasonable bandwidth (typically <100 GB/month per IP); valid HTTP referer header pointing to the actual application; clearly visible attribution; no hot-linking from competing services; no automated 'scraping' of large tile areas. Violation can result in IP blocking and exclusion. Many small projects use OSM tiles within policy; larger projects use commercial alternatives (Mapbox, MapTiler) or self-host (the Switch2OSM project provides setup guides).

Sources

  1. OpenStreetMap FoundationOSM Tile Usage Policy and tile-server operations documentation · https://operations.osmfoundation.org/policies/tiles/ · Accessed .
  2. MapboxMapbox tile delivery architecture — CDN-backed tile distribution · https://docs.mapbox.com/ · Accessed .
  3. AWSAWS CloudFront — caching maps and tiles best practices · https://aws.amazon.com/cloudfront/ · Accessed .
  4. IETFRFC 9113 (HTTP/2) and RFC 9114 (HTTP/3) — protocols used for tile delivery · https://www.rfc-editor.org/rfc/rfc9113 · Accessed .

Cite this article

APA format:

Steve K. (2026). Tile Servers and Caching Explained. Coordinately. https://coordinately.org/learn/tile-servers-and-caching-explained

BibTeX:

@misc{coordinately_tileserversand_2026,
  author = {K., Steve},
  title  = {Tile Servers and Caching Explained},
  year   = {2026},
  publisher = {Coordinately},
  url    = {https://coordinately.org/learn/tile-servers-and-caching-explained},
  note   = {Accessed: 2026-06-05}
}