Skip to content

noeulnight/osmproxy

Repository files navigation

osmproxy

osmproxy is a small HTTP tile proxy for slippy-map tiles. It fetches tiles from configured upstream map providers, stores them in an S3-compatible object store, and serves cached responses on later requests.

Features

  • S3-compatible tile caching
  • Multiple named map origins through PROXY_MAPS
  • Origin fallback on cache miss
  • Stale cached tile serving with background refresh
  • Cache inspection endpoint
  • Simple Express HTTP API

Architecture

flowchart LR
  client["Map client"] --> proxy["osmproxy"]
  proxy --> allowlist["Map allowlist\nPROXY_MAPS"]
  allowlist --> cache{"Tile in S3 cache?"}
  cache -- "fresh hit" --> s3["S3-compatible storage"]
  s3 --> proxy
  cache -- "miss or stale refresh" --> origin["Upstream tile origin"]
  origin --> proxy
  proxy --> store["Store or refresh cached tile"]
  store --> s3
  proxy --> client
Loading

Requirements

  • Node.js 20 or newer
  • An S3-compatible object store

Installation

npm install
cp .env.example .env

Configuration

Variable Description Default
PORT HTTP server port 3000
AWS_REGION S3 region ap-northeast-2
S3_BUCKET Bucket used for cached tiles Required
S3_ENDPOINT Optional S3-compatible endpoint unset
S3_FORCE_PATH_STYLE Use path-style S3 requests false
CACHE_TTL_MS Freshness window for cached tiles 300000
PROXY_MAPS Comma-separated name=url origin map Required

Example:

PORT=3000
AWS_REGION=ap-northeast-2
S3_BUCKET=tiles
S3_ENDPOINT=
S3_FORCE_PATH_STYLE=false
CACHE_TTL_MS=300000
PROXY_MAPS=base=https://tile.openstreetmap.org

PROXY_MAPS values are exposed as /tiles/:map/... route names. Origin URLs should not include a trailing slash.

Usage

Run in development mode:

npm run dev

Build and start:

npm run build
npm start

Run tests:

npm test

API

Health

GET /health

Response:

{
  "ok": true,
  "maps": ["base"]
}

Fetch a Tile

GET /tiles/:map/:z/:x/:y.:ext

Example:

GET /tiles/base/1/2/3.png

Tile paths use standard slippy-map order: {z}/{x}/{y}.{ext}.

Responses include an X-Cache header:

Value Meaning
HIT Tile was served from fresh cache
MISS Tile was fetched from origin and stored
STALE Stale cached tile was served while refresh runs in the background

Inspect Cache Metadata

GET /tiles/:map/:z/:x/:y.:ext/info

Example:

GET /tiles/base/1/2/3.png/info

Returns cache metadata when the tile exists in storage. Returns cached: false when the tile is absent.

Performance

osmproxy is designed to reduce repeated upstream tile requests by serving cached tiles directly from S3-compatible storage. The largest benefit appears on warm-cache traffic, where the proxy can avoid origin latency and return the stored tile immediately.

Example warm-cache benchmark from one deployment:

Metric Cached proxy Upstream origin Comparison
Success rate 100% 100% Same
Median total time 21.3 ms 883.2 ms Proxy 41.5x faster
Mean total time 22.1 ms 836.1 ms Proxy 37.9x faster
p95 total time 29.4 ms 1103.5 ms Proxy 37.5x faster
Median TTFB 20.5 ms 882.4 ms Proxy 43.0x faster
Mean tile size 20.1 KiB 20.1 KiB Same

Benchmark shape:

  • 9 tile coordinates
  • 1 warmup pass
  • 45 measured requests per endpoint
  • Same client network location
  • Same tile content and image format

Actual results depend on cache state, S3 provider latency, upstream latency, tile size, and user region. Cold-cache requests include origin fetch and storage write overhead, so they are expected to be slower than warm-cache hits.

License

This project is licensed under the MIT License.

Map tiles, map data, and rendered assets served through this proxy remain subject to the license, attribution requirements, rate limits, and usage policies of their upstream providers. Configure and operate this proxy only in compliance with those provider terms.

About

openstreetmap proxy

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors