This project provides a high-performance elevation service from a Cloud-Optimized GeoTIFF (COG) file. It exposes the service via both a traditional HTTP REST API and a modern, high-performance gRPC API. The service is optimized for low-latency queries by using on-demand tile fetching, in-memory caching, and concurrent request handling.
The primary data source is Global Ensemble Digital Terrain Model 30m (GEDTM30).
- Dual API Support: Access elevation data through both a simple HTTP REST API and a typed, high-performance gRPC API.
- Cloud-Optimized GeoTIFF (COG) Support: Efficiently reads data from large GeoTIFF files without needing to download the entire file. It fetches only the required header information and raster tiles on-demand.
- Flexible Data Sources: Works seamlessly with both remote COGs (via HTTP range requests) and local
.tifffiles. - High-Performance Caching: Utilizes an in-memory LRU cache (
ccache) to store processed tile data. This dramatically reduces I/O and CPU load for subsequent requests to nearby geographic areas. - Concurrent Request Handling: Implements a
singleflightmechanism to prevent the "thundering herd" problem, ensuring that concurrent requests for the same uncached tile result in only one fetch operation. - Intelligent Prefetching: When a tile is requested, its neighbors are preemptively and concurrently fetched in the background to improve latency for spatially coherent queries (like generating a profile).
- Production-Ready Structure: Includes separate servers for the API, health checks (
gRPC), and metrics (Prometheus), all managed with graceful shutdown.
The server is defaulting to the most recent url for GEDTM30, but you probably want to download the file and host it yourself (310GB for the whole world), since no guarantee this url will always be available.
You can also extract some extend, note that you will need to rebuild the file as follow:
gdal_translate -of COG \
-co COMPRESS=DEFLATE \
-co ZLEVEL=6 \
-co TILED=YES \
extend.tiff extend-cog.tiffgo install github.com/akhenakh/gedtm30api@latest
gedtm30api- LOG_LEVEL envDefault:"INFO"
- HTTP_PORT envDefault:"8080"
- API_PORT envDefault:"9200"
- HEALTH_PORT envDefault:"6666"
- METRICS_PORT envDefault:"8888"
- COG_SOURCE envDefault:"https://s3.opengeohub.org/global/edtm/gedtm_rf_m_30m_s_20060101_20151231_go_epsg.4326.3855_v20250611.tif"`
- CACHE_MAX_SIZE envDefault:"512" number of tiles to keep in the cache
- CACHE_ITEMS_TO_PRUNE envDefault:"32" number of tiles to prune from the cache
The server will start multiple services on different ports:
- HTTP REST & Web UI:
http://localhost:8080 - Prometheus Metrics:
http://localhost:8888/metrics - gRPC API:
localhost:9200 - gRPC Health Checks:
localhost:6666
To use a local GeoTIFF file, set the COG_SOURCE environment variable to the file path:
COG_SOURCE="/path/to/your/data.tiff" gedtm30apiThe REST API is available on port 8080 by default.
Returns the elevation in meters for a single latitude/longitude coordinate.
-
Endpoint:
/getElevation/{lat}/{lng} -
Method:
GET -
URL Parameters:
lat: Latitude (float)lng: Longitude (float)
-
Example Request:
curl http://localhost:8080/getElevation/45.8329/6.8648
-
Example Success Response (
200 OK):{ "elevation": 4805.3, "latitude": 45.8329, "longitude": 6.8648 }
Returns a list of elevation points along a path defined by two or more coordinates.
-
Endpoint:
/getProfile/ -
Method:
POST -
Request Body: A JSON object containing a list of
[latitude, longitude]pairs. -
Example Request:
curl -X POST -H "Content-Type: application/json" \ -d '{"coordinates":[[46.5, 6.5], [46.6, 6.6]]}' \ http://localhost:8080/getProfile/
-
Example Success Response (
200 OK): A JSON array where each element is[latitude, longitude, elevation].[ [46.5, 6.5, 435.6], [46.500135, 6.500150, 436.1], [46.500270, 6.500300, 436.8], ... [46.6, 6.6, 612.9] ]
The service definition can be found in proto/elevation.proto.
Retrieves the elevation for a single coordinate.
-
Request:
ElevationRequestmessage ElevationRequest { double latitude = 1; double longitude = 2; }
-
Response:
ElevationResponsemessage ElevationResponse { float elevation = 1; }
-
Example with
grpcurl:grpcurl -plaintext -d '{"latitude": 45.8329, "longitude": 6.8648}' \ localhost:9200 elevationapi.ElevationService.GetElevation
Retrieves an elevation profile along a path.
-
Request:
ProfileRequestmessage ProfileRequest { repeated Point points = 1; } message Point { double latitude = 1; double longitude = 2; }
-
Response:
ProfileResponsemessage ProfileResponse { repeated ElevationPoint points = 1; } message ElevationPoint { double latitude = 1; double longitude = 2; float elevation = 3; }
-
Example with
grpcurl:grpcurl -plaintext -d '{"points": [{"latitude": 46.5, "longitude": 6.5}, {"latitude": 46.6, "longitude": 6.6}]}' \ localhost:9200 elevationapi.ElevationService.GetProfile
A simple web UI is available at http://localhost:8080. It allows you to interactively click on a map to get single-point elevations or generate and visualize elevation profiles.
The server uses a cache to store recently accessed tiles. The cache size can be configured using the CACHE_MAX_SIZE environment variable. When the cache reaches its maximum size, the least recently used tiles are pruned to make room for new ones. The number of tiles to prune can be configured using the CACHE_ITEMS_TO_PRUNE environment variable.
With 512 × 512 tiles, since a pixel is using 4 bytes (for a float32 or int32), 262,144 pixels × 4 bytes/pixel = 1,048,576 bytes.
So 128 tiles would account for 128 MiB in memory.
The geoTIFF library has only been tested with this specific dataset and does not support all the GeoTIFF spec (for example only DEFLATE compression is supported). It is reusing some code from geotiff.
